]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
Merge remote-tracking branch 'openstreetmap/pull/1375'
[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.1';
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 = castPath(path, object);
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       path = castPath(path, object);
3266       object = parent(object, path);
3267       var func = object == null ? object : object[toKey(last(path))];
3268       return func == null ? undefined : apply(func, object, args);
3269     }
3270
3271     /**
3272      * The base implementation of `_.isArguments`.
3273      *
3274      * @private
3275      * @param {*} value The value to check.
3276      * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3277      */
3278     function baseIsArguments(value) {
3279       return isObjectLike(value) && baseGetTag(value) == argsTag;
3280     }
3281
3282     /**
3283      * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
3284      *
3285      * @private
3286      * @param {*} value The value to check.
3287      * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
3288      */
3289     function baseIsArrayBuffer(value) {
3290       return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
3291     }
3292
3293     /**
3294      * The base implementation of `_.isDate` without Node.js optimizations.
3295      *
3296      * @private
3297      * @param {*} value The value to check.
3298      * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
3299      */
3300     function baseIsDate(value) {
3301       return isObjectLike(value) && baseGetTag(value) == dateTag;
3302     }
3303
3304     /**
3305      * The base implementation of `_.isEqual` which supports partial comparisons
3306      * and tracks traversed objects.
3307      *
3308      * @private
3309      * @param {*} value The value to compare.
3310      * @param {*} other The other value to compare.
3311      * @param {boolean} bitmask The bitmask flags.
3312      *  1 - Unordered comparison
3313      *  2 - Partial comparison
3314      * @param {Function} [customizer] The function to customize comparisons.
3315      * @param {Object} [stack] Tracks traversed `value` and `other` objects.
3316      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3317      */
3318     function baseIsEqual(value, other, bitmask, customizer, stack) {
3319       if (value === other) {
3320         return true;
3321       }
3322       if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
3323         return value !== value && other !== other;
3324       }
3325       return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
3326     }
3327
3328     /**
3329      * A specialized version of `baseIsEqual` for arrays and objects which performs
3330      * deep comparisons and tracks traversed objects enabling objects with circular
3331      * references to be compared.
3332      *
3333      * @private
3334      * @param {Object} object The object to compare.
3335      * @param {Object} other The other object to compare.
3336      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3337      * @param {Function} customizer The function to customize comparisons.
3338      * @param {Function} equalFunc The function to determine equivalents of values.
3339      * @param {Object} [stack] Tracks traversed `object` and `other` objects.
3340      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3341      */
3342     function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
3343       var objIsArr = isArray(object),
3344           othIsArr = isArray(other),
3345           objTag = arrayTag,
3346           othTag = arrayTag;
3347
3348       if (!objIsArr) {
3349         objTag = getTag(object);
3350         objTag = objTag == argsTag ? objectTag : objTag;
3351       }
3352       if (!othIsArr) {
3353         othTag = getTag(other);
3354         othTag = othTag == argsTag ? objectTag : othTag;
3355       }
3356       var objIsObj = objTag == objectTag,
3357           othIsObj = othTag == objectTag,
3358           isSameTag = objTag == othTag;
3359
3360       if (isSameTag && isBuffer(object)) {
3361         if (!isBuffer(other)) {
3362           return false;
3363         }
3364         objIsArr = true;
3365         objIsObj = false;
3366       }
3367       if (isSameTag && !objIsObj) {
3368         stack || (stack = new Stack);
3369         return (objIsArr || isTypedArray(object))
3370           ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
3371           : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
3372       }
3373       if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
3374         var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
3375             othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
3376
3377         if (objIsWrapped || othIsWrapped) {
3378           var objUnwrapped = objIsWrapped ? object.value() : object,
3379               othUnwrapped = othIsWrapped ? other.value() : other;
3380
3381           stack || (stack = new Stack);
3382           return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
3383         }
3384       }
3385       if (!isSameTag) {
3386         return false;
3387       }
3388       stack || (stack = new Stack);
3389       return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
3390     }
3391
3392     /**
3393      * The base implementation of `_.isMap` without Node.js optimizations.
3394      *
3395      * @private
3396      * @param {*} value The value to check.
3397      * @returns {boolean} Returns `true` if `value` is a map, else `false`.
3398      */
3399     function baseIsMap(value) {
3400       return isObjectLike(value) && getTag(value) == mapTag;
3401     }
3402
3403     /**
3404      * The base implementation of `_.isMatch` without support for iteratee shorthands.
3405      *
3406      * @private
3407      * @param {Object} object The object to inspect.
3408      * @param {Object} source The object of property values to match.
3409      * @param {Array} matchData The property names, values, and compare flags to match.
3410      * @param {Function} [customizer] The function to customize comparisons.
3411      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
3412      */
3413     function baseIsMatch(object, source, matchData, customizer) {
3414       var index = matchData.length,
3415           length = index,
3416           noCustomizer = !customizer;
3417
3418       if (object == null) {
3419         return !length;
3420       }
3421       object = Object(object);
3422       while (index--) {
3423         var data = matchData[index];
3424         if ((noCustomizer && data[2])
3425               ? data[1] !== object[data[0]]
3426               : !(data[0] in object)
3427             ) {
3428           return false;
3429         }
3430       }
3431       while (++index < length) {
3432         data = matchData[index];
3433         var key = data[0],
3434             objValue = object[key],
3435             srcValue = data[1];
3436
3437         if (noCustomizer && data[2]) {
3438           if (objValue === undefined && !(key in object)) {
3439             return false;
3440           }
3441         } else {
3442           var stack = new Stack;
3443           if (customizer) {
3444             var result = customizer(objValue, srcValue, key, object, source, stack);
3445           }
3446           if (!(result === undefined
3447                 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
3448                 : result
3449               )) {
3450             return false;
3451           }
3452         }
3453       }
3454       return true;
3455     }
3456
3457     /**
3458      * The base implementation of `_.isNative` without bad shim checks.
3459      *
3460      * @private
3461      * @param {*} value The value to check.
3462      * @returns {boolean} Returns `true` if `value` is a native function,
3463      *  else `false`.
3464      */
3465     function baseIsNative(value) {
3466       if (!isObject(value) || isMasked(value)) {
3467         return false;
3468       }
3469       var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
3470       return pattern.test(toSource(value));
3471     }
3472
3473     /**
3474      * The base implementation of `_.isRegExp` without Node.js optimizations.
3475      *
3476      * @private
3477      * @param {*} value The value to check.
3478      * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
3479      */
3480     function baseIsRegExp(value) {
3481       return isObjectLike(value) && baseGetTag(value) == regexpTag;
3482     }
3483
3484     /**
3485      * The base implementation of `_.isSet` without Node.js optimizations.
3486      *
3487      * @private
3488      * @param {*} value The value to check.
3489      * @returns {boolean} Returns `true` if `value` is a set, else `false`.
3490      */
3491     function baseIsSet(value) {
3492       return isObjectLike(value) && getTag(value) == setTag;
3493     }
3494
3495     /**
3496      * The base implementation of `_.isTypedArray` without Node.js optimizations.
3497      *
3498      * @private
3499      * @param {*} value The value to check.
3500      * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3501      */
3502     function baseIsTypedArray(value) {
3503       return isObjectLike(value) &&
3504         isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
3505     }
3506
3507     /**
3508      * The base implementation of `_.iteratee`.
3509      *
3510      * @private
3511      * @param {*} [value=_.identity] The value to convert to an iteratee.
3512      * @returns {Function} Returns the iteratee.
3513      */
3514     function baseIteratee(value) {
3515       // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
3516       // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
3517       if (typeof value == 'function') {
3518         return value;
3519       }
3520       if (value == null) {
3521         return identity;
3522       }
3523       if (typeof value == 'object') {
3524         return isArray(value)
3525           ? baseMatchesProperty(value[0], value[1])
3526           : baseMatches(value);
3527       }
3528       return property(value);
3529     }
3530
3531     /**
3532      * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
3533      *
3534      * @private
3535      * @param {Object} object The object to query.
3536      * @returns {Array} Returns the array of property names.
3537      */
3538     function baseKeys(object) {
3539       if (!isPrototype(object)) {
3540         return nativeKeys(object);
3541       }
3542       var result = [];
3543       for (var key in Object(object)) {
3544         if (hasOwnProperty.call(object, key) && key != 'constructor') {
3545           result.push(key);
3546         }
3547       }
3548       return result;
3549     }
3550
3551     /**
3552      * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
3553      *
3554      * @private
3555      * @param {Object} object The object to query.
3556      * @returns {Array} Returns the array of property names.
3557      */
3558     function baseKeysIn(object) {
3559       if (!isObject(object)) {
3560         return nativeKeysIn(object);
3561       }
3562       var isProto = isPrototype(object),
3563           result = [];
3564
3565       for (var key in object) {
3566         if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
3567           result.push(key);
3568         }
3569       }
3570       return result;
3571     }
3572
3573     /**
3574      * The base implementation of `_.lt` which doesn't coerce arguments.
3575      *
3576      * @private
3577      * @param {*} value The value to compare.
3578      * @param {*} other The other value to compare.
3579      * @returns {boolean} Returns `true` if `value` is less than `other`,
3580      *  else `false`.
3581      */
3582     function baseLt(value, other) {
3583       return value < other;
3584     }
3585
3586     /**
3587      * The base implementation of `_.map` without support for iteratee shorthands.
3588      *
3589      * @private
3590      * @param {Array|Object} collection The collection to iterate over.
3591      * @param {Function} iteratee The function invoked per iteration.
3592      * @returns {Array} Returns the new mapped array.
3593      */
3594     function baseMap(collection, iteratee) {
3595       var index = -1,
3596           result = isArrayLike(collection) ? Array(collection.length) : [];
3597
3598       baseEach(collection, function(value, key, collection) {
3599         result[++index] = iteratee(value, key, collection);
3600       });
3601       return result;
3602     }
3603
3604     /**
3605      * The base implementation of `_.matches` which doesn't clone `source`.
3606      *
3607      * @private
3608      * @param {Object} source The object of property values to match.
3609      * @returns {Function} Returns the new spec function.
3610      */
3611     function baseMatches(source) {
3612       var matchData = getMatchData(source);
3613       if (matchData.length == 1 && matchData[0][2]) {
3614         return matchesStrictComparable(matchData[0][0], matchData[0][1]);
3615       }
3616       return function(object) {
3617         return object === source || baseIsMatch(object, source, matchData);
3618       };
3619     }
3620
3621     /**
3622      * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
3623      *
3624      * @private
3625      * @param {string} path The path of the property to get.
3626      * @param {*} srcValue The value to match.
3627      * @returns {Function} Returns the new spec function.
3628      */
3629     function baseMatchesProperty(path, srcValue) {
3630       if (isKey(path) && isStrictComparable(srcValue)) {
3631         return matchesStrictComparable(toKey(path), srcValue);
3632       }
3633       return function(object) {
3634         var objValue = get(object, path);
3635         return (objValue === undefined && objValue === srcValue)
3636           ? hasIn(object, path)
3637           : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
3638       };
3639     }
3640
3641     /**
3642      * The base implementation of `_.merge` without support for multiple sources.
3643      *
3644      * @private
3645      * @param {Object} object The destination object.
3646      * @param {Object} source The source object.
3647      * @param {number} srcIndex The index of `source`.
3648      * @param {Function} [customizer] The function to customize merged values.
3649      * @param {Object} [stack] Tracks traversed source values and their merged
3650      *  counterparts.
3651      */
3652     function baseMerge(object, source, srcIndex, customizer, stack) {
3653       if (object === source) {
3654         return;
3655       }
3656       baseFor(source, function(srcValue, key) {
3657         if (isObject(srcValue)) {
3658           stack || (stack = new Stack);
3659           baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
3660         }
3661         else {
3662           var newValue = customizer
3663             ? customizer(object[key], srcValue, (key + ''), object, source, stack)
3664             : undefined;
3665
3666           if (newValue === undefined) {
3667             newValue = srcValue;
3668           }
3669           assignMergeValue(object, key, newValue);
3670         }
3671       }, keysIn);
3672     }
3673
3674     /**
3675      * A specialized version of `baseMerge` for arrays and objects which performs
3676      * deep merges and tracks traversed objects enabling objects with circular
3677      * references to be merged.
3678      *
3679      * @private
3680      * @param {Object} object The destination object.
3681      * @param {Object} source The source object.
3682      * @param {string} key The key of the value to merge.
3683      * @param {number} srcIndex The index of `source`.
3684      * @param {Function} mergeFunc The function to merge values.
3685      * @param {Function} [customizer] The function to customize assigned values.
3686      * @param {Object} [stack] Tracks traversed source values and their merged
3687      *  counterparts.
3688      */
3689     function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
3690       var objValue = object[key],
3691           srcValue = source[key],
3692           stacked = stack.get(srcValue);
3693
3694       if (stacked) {
3695         assignMergeValue(object, key, stacked);
3696         return;
3697       }
3698       var newValue = customizer
3699         ? customizer(objValue, srcValue, (key + ''), object, source, stack)
3700         : undefined;
3701
3702       var isCommon = newValue === undefined;
3703
3704       if (isCommon) {
3705         var isArr = isArray(srcValue),
3706             isBuff = !isArr && isBuffer(srcValue),
3707             isTyped = !isArr && !isBuff && isTypedArray(srcValue);
3708
3709         newValue = srcValue;
3710         if (isArr || isBuff || isTyped) {
3711           if (isArray(objValue)) {
3712             newValue = objValue;
3713           }
3714           else if (isArrayLikeObject(objValue)) {
3715             newValue = copyArray(objValue);
3716           }
3717           else if (isBuff) {
3718             isCommon = false;
3719             newValue = cloneBuffer(srcValue, true);
3720           }
3721           else if (isTyped) {
3722             isCommon = false;
3723             newValue = cloneTypedArray(srcValue, true);
3724           }
3725           else {
3726             newValue = [];
3727           }
3728         }
3729         else if (isPlainObject(srcValue) || isArguments(srcValue)) {
3730           newValue = objValue;
3731           if (isArguments(objValue)) {
3732             newValue = toPlainObject(objValue);
3733           }
3734           else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
3735             newValue = initCloneObject(srcValue);
3736           }
3737         }
3738         else {
3739           isCommon = false;
3740         }
3741       }
3742       if (isCommon) {
3743         // Recursively merge objects and arrays (susceptible to call stack limits).
3744         stack.set(srcValue, newValue);
3745         mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
3746         stack['delete'](srcValue);
3747       }
3748       assignMergeValue(object, key, newValue);
3749     }
3750
3751     /**
3752      * The base implementation of `_.nth` which doesn't coerce arguments.
3753      *
3754      * @private
3755      * @param {Array} array The array to query.
3756      * @param {number} n The index of the element to return.
3757      * @returns {*} Returns the nth element of `array`.
3758      */
3759     function baseNth(array, n) {
3760       var length = array.length;
3761       if (!length) {
3762         return;
3763       }
3764       n += n < 0 ? length : 0;
3765       return isIndex(n, length) ? array[n] : undefined;
3766     }
3767
3768     /**
3769      * The base implementation of `_.orderBy` without param guards.
3770      *
3771      * @private
3772      * @param {Array|Object} collection The collection to iterate over.
3773      * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
3774      * @param {string[]} orders The sort orders of `iteratees`.
3775      * @returns {Array} Returns the new sorted array.
3776      */
3777     function baseOrderBy(collection, iteratees, orders) {
3778       var index = -1;
3779       iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));
3780
3781       var result = baseMap(collection, function(value, key, collection) {
3782         var criteria = arrayMap(iteratees, function(iteratee) {
3783           return iteratee(value);
3784         });
3785         return { 'criteria': criteria, 'index': ++index, 'value': value };
3786       });
3787
3788       return baseSortBy(result, function(object, other) {
3789         return compareMultiple(object, other, orders);
3790       });
3791     }
3792
3793     /**
3794      * The base implementation of `_.pick` without support for individual
3795      * property identifiers.
3796      *
3797      * @private
3798      * @param {Object} object The source object.
3799      * @param {string[]} paths The property paths to pick.
3800      * @returns {Object} Returns the new object.
3801      */
3802     function basePick(object, paths) {
3803       object = Object(object);
3804       return basePickBy(object, paths, function(value, path) {
3805         return hasIn(object, path);
3806       });
3807     }
3808
3809     /**
3810      * The base implementation of  `_.pickBy` without support for iteratee shorthands.
3811      *
3812      * @private
3813      * @param {Object} object The source object.
3814      * @param {string[]} paths The property paths to pick.
3815      * @param {Function} predicate The function invoked per property.
3816      * @returns {Object} Returns the new object.
3817      */
3818     function basePickBy(object, paths, predicate) {
3819       var index = -1,
3820           length = paths.length,
3821           result = {};
3822
3823       while (++index < length) {
3824         var path = paths[index],
3825             value = baseGet(object, path);
3826
3827         if (predicate(value, path)) {
3828           baseSet(result, path, value);
3829         }
3830       }
3831       return result;
3832     }
3833
3834     /**
3835      * A specialized version of `baseProperty` which supports deep paths.
3836      *
3837      * @private
3838      * @param {Array|string} path The path of the property to get.
3839      * @returns {Function} Returns the new accessor function.
3840      */
3841     function basePropertyDeep(path) {
3842       return function(object) {
3843         return baseGet(object, path);
3844       };
3845     }
3846
3847     /**
3848      * The base implementation of `_.pullAllBy` without support for iteratee
3849      * shorthands.
3850      *
3851      * @private
3852      * @param {Array} array The array to modify.
3853      * @param {Array} values The values to remove.
3854      * @param {Function} [iteratee] The iteratee invoked per element.
3855      * @param {Function} [comparator] The comparator invoked per element.
3856      * @returns {Array} Returns `array`.
3857      */
3858     function basePullAll(array, values, iteratee, comparator) {
3859       var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
3860           index = -1,
3861           length = values.length,
3862           seen = array;
3863
3864       if (array === values) {
3865         values = copyArray(values);
3866       }
3867       if (iteratee) {
3868         seen = arrayMap(array, baseUnary(iteratee));
3869       }
3870       while (++index < length) {
3871         var fromIndex = 0,
3872             value = values[index],
3873             computed = iteratee ? iteratee(value) : value;
3874
3875         while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
3876           if (seen !== array) {
3877             splice.call(seen, fromIndex, 1);
3878           }
3879           splice.call(array, fromIndex, 1);
3880         }
3881       }
3882       return array;
3883     }
3884
3885     /**
3886      * The base implementation of `_.pullAt` without support for individual
3887      * indexes or capturing the removed elements.
3888      *
3889      * @private
3890      * @param {Array} array The array to modify.
3891      * @param {number[]} indexes The indexes of elements to remove.
3892      * @returns {Array} Returns `array`.
3893      */
3894     function basePullAt(array, indexes) {
3895       var length = array ? indexes.length : 0,
3896           lastIndex = length - 1;
3897
3898       while (length--) {
3899         var index = indexes[length];
3900         if (length == lastIndex || index !== previous) {
3901           var previous = index;
3902           if (isIndex(index)) {
3903             splice.call(array, index, 1);
3904           }
3905           else {
3906             var path = castPath(index, array),
3907                 object = parent(array, path);
3908
3909             if (object != null) {
3910               delete object[toKey(last(path))];
3911             }
3912           }
3913         }
3914       }
3915       return array;
3916     }
3917
3918     /**
3919      * The base implementation of `_.random` without support for returning
3920      * floating-point numbers.
3921      *
3922      * @private
3923      * @param {number} lower The lower bound.
3924      * @param {number} upper The upper bound.
3925      * @returns {number} Returns the random number.
3926      */
3927     function baseRandom(lower, upper) {
3928       return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
3929     }
3930
3931     /**
3932      * The base implementation of `_.range` and `_.rangeRight` which doesn't
3933      * coerce arguments.
3934      *
3935      * @private
3936      * @param {number} start The start of the range.
3937      * @param {number} end The end of the range.
3938      * @param {number} step The value to increment or decrement by.
3939      * @param {boolean} [fromRight] Specify iterating from right to left.
3940      * @returns {Array} Returns the range of numbers.
3941      */
3942     function baseRange(start, end, step, fromRight) {
3943       var index = -1,
3944           length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
3945           result = Array(length);
3946
3947       while (length--) {
3948         result[fromRight ? length : ++index] = start;
3949         start += step;
3950       }
3951       return result;
3952     }
3953
3954     /**
3955      * The base implementation of `_.repeat` which doesn't coerce arguments.
3956      *
3957      * @private
3958      * @param {string} string The string to repeat.
3959      * @param {number} n The number of times to repeat the string.
3960      * @returns {string} Returns the repeated string.
3961      */
3962     function baseRepeat(string, n) {
3963       var result = '';
3964       if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
3965         return result;
3966       }
3967       // Leverage the exponentiation by squaring algorithm for a faster repeat.
3968       // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
3969       do {
3970         if (n % 2) {
3971           result += string;
3972         }
3973         n = nativeFloor(n / 2);
3974         if (n) {
3975           string += string;
3976         }
3977       } while (n);
3978
3979       return result;
3980     }
3981
3982     /**
3983      * The base implementation of `_.rest` which doesn't validate or coerce arguments.
3984      *
3985      * @private
3986      * @param {Function} func The function to apply a rest parameter to.
3987      * @param {number} [start=func.length-1] The start position of the rest parameter.
3988      * @returns {Function} Returns the new function.
3989      */
3990     function baseRest(func, start) {
3991       return setToString(overRest(func, start, identity), func + '');
3992     }
3993
3994     /**
3995      * The base implementation of `_.sample`.
3996      *
3997      * @private
3998      * @param {Array|Object} collection The collection to sample.
3999      * @returns {*} Returns the random element.
4000      */
4001     function baseSample(collection) {
4002       return arraySample(values(collection));
4003     }
4004
4005     /**
4006      * The base implementation of `_.sampleSize` without param guards.
4007      *
4008      * @private
4009      * @param {Array|Object} collection The collection to sample.
4010      * @param {number} n The number of elements to sample.
4011      * @returns {Array} Returns the random elements.
4012      */
4013     function baseSampleSize(collection, n) {
4014       var array = values(collection);
4015       return shuffleSelf(array, baseClamp(n, 0, array.length));
4016     }
4017
4018     /**
4019      * The base implementation of `_.set`.
4020      *
4021      * @private
4022      * @param {Object} object The object to modify.
4023      * @param {Array|string} path The path of the property to set.
4024      * @param {*} value The value to set.
4025      * @param {Function} [customizer] The function to customize path creation.
4026      * @returns {Object} Returns `object`.
4027      */
4028     function baseSet(object, path, value, customizer) {
4029       if (!isObject(object)) {
4030         return object;
4031       }
4032       path = castPath(path, object);
4033
4034       var index = -1,
4035           length = path.length,
4036           lastIndex = length - 1,
4037           nested = object;
4038
4039       while (nested != null && ++index < length) {
4040         var key = toKey(path[index]),
4041             newValue = value;
4042
4043         if (index != lastIndex) {
4044           var objValue = nested[key];
4045           newValue = customizer ? customizer(objValue, key, nested) : undefined;
4046           if (newValue === undefined) {
4047             newValue = isObject(objValue)
4048               ? objValue
4049               : (isIndex(path[index + 1]) ? [] : {});
4050           }
4051         }
4052         assignValue(nested, key, newValue);
4053         nested = nested[key];
4054       }
4055       return object;
4056     }
4057
4058     /**
4059      * The base implementation of `setData` without support for hot loop shorting.
4060      *
4061      * @private
4062      * @param {Function} func The function to associate metadata with.
4063      * @param {*} data The metadata.
4064      * @returns {Function} Returns `func`.
4065      */
4066     var baseSetData = !metaMap ? identity : function(func, data) {
4067       metaMap.set(func, data);
4068       return func;
4069     };
4070
4071     /**
4072      * The base implementation of `setToString` without support for hot loop shorting.
4073      *
4074      * @private
4075      * @param {Function} func The function to modify.
4076      * @param {Function} string The `toString` result.
4077      * @returns {Function} Returns `func`.
4078      */
4079     var baseSetToString = !defineProperty ? identity : function(func, string) {
4080       return defineProperty(func, 'toString', {
4081         'configurable': true,
4082         'enumerable': false,
4083         'value': constant(string),
4084         'writable': true
4085       });
4086     };
4087
4088     /**
4089      * The base implementation of `_.shuffle`.
4090      *
4091      * @private
4092      * @param {Array|Object} collection The collection to shuffle.
4093      * @returns {Array} Returns the new shuffled array.
4094      */
4095     function baseShuffle(collection) {
4096       return shuffleSelf(values(collection));
4097     }
4098
4099     /**
4100      * The base implementation of `_.slice` without an iteratee call guard.
4101      *
4102      * @private
4103      * @param {Array} array The array to slice.
4104      * @param {number} [start=0] The start position.
4105      * @param {number} [end=array.length] The end position.
4106      * @returns {Array} Returns the slice of `array`.
4107      */
4108     function baseSlice(array, start, end) {
4109       var index = -1,
4110           length = array.length;
4111
4112       if (start < 0) {
4113         start = -start > length ? 0 : (length + start);
4114       }
4115       end = end > length ? length : end;
4116       if (end < 0) {
4117         end += length;
4118       }
4119       length = start > end ? 0 : ((end - start) >>> 0);
4120       start >>>= 0;
4121
4122       var result = Array(length);
4123       while (++index < length) {
4124         result[index] = array[index + start];
4125       }
4126       return result;
4127     }
4128
4129     /**
4130      * The base implementation of `_.some` without support for iteratee shorthands.
4131      *
4132      * @private
4133      * @param {Array|Object} collection The collection to iterate over.
4134      * @param {Function} predicate The function invoked per iteration.
4135      * @returns {boolean} Returns `true` if any element passes the predicate check,
4136      *  else `false`.
4137      */
4138     function baseSome(collection, predicate) {
4139       var result;
4140
4141       baseEach(collection, function(value, index, collection) {
4142         result = predicate(value, index, collection);
4143         return !result;
4144       });
4145       return !!result;
4146     }
4147
4148     /**
4149      * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
4150      * performs a binary search of `array` to determine the index at which `value`
4151      * should be inserted into `array` in order to maintain its sort order.
4152      *
4153      * @private
4154      * @param {Array} array The sorted array to inspect.
4155      * @param {*} value The value to evaluate.
4156      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4157      * @returns {number} Returns the index at which `value` should be inserted
4158      *  into `array`.
4159      */
4160     function baseSortedIndex(array, value, retHighest) {
4161       var low = 0,
4162           high = array == null ? low : array.length;
4163
4164       if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
4165         while (low < high) {
4166           var mid = (low + high) >>> 1,
4167               computed = array[mid];
4168
4169           if (computed !== null && !isSymbol(computed) &&
4170               (retHighest ? (computed <= value) : (computed < value))) {
4171             low = mid + 1;
4172           } else {
4173             high = mid;
4174           }
4175         }
4176         return high;
4177       }
4178       return baseSortedIndexBy(array, value, identity, retHighest);
4179     }
4180
4181     /**
4182      * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
4183      * which invokes `iteratee` for `value` and each element of `array` to compute
4184      * their sort ranking. The iteratee is invoked with one argument; (value).
4185      *
4186      * @private
4187      * @param {Array} array The sorted array to inspect.
4188      * @param {*} value The value to evaluate.
4189      * @param {Function} iteratee The iteratee invoked per element.
4190      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4191      * @returns {number} Returns the index at which `value` should be inserted
4192      *  into `array`.
4193      */
4194     function baseSortedIndexBy(array, value, iteratee, retHighest) {
4195       value = iteratee(value);
4196
4197       var low = 0,
4198           high = array == null ? 0 : array.length,
4199           valIsNaN = value !== value,
4200           valIsNull = value === null,
4201           valIsSymbol = isSymbol(value),
4202           valIsUndefined = value === undefined;
4203
4204       while (low < high) {
4205         var mid = nativeFloor((low + high) / 2),
4206             computed = iteratee(array[mid]),
4207             othIsDefined = computed !== undefined,
4208             othIsNull = computed === null,
4209             othIsReflexive = computed === computed,
4210             othIsSymbol = isSymbol(computed);
4211
4212         if (valIsNaN) {
4213           var setLow = retHighest || othIsReflexive;
4214         } else if (valIsUndefined) {
4215           setLow = othIsReflexive && (retHighest || othIsDefined);
4216         } else if (valIsNull) {
4217           setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
4218         } else if (valIsSymbol) {
4219           setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
4220         } else if (othIsNull || othIsSymbol) {
4221           setLow = false;
4222         } else {
4223           setLow = retHighest ? (computed <= value) : (computed < value);
4224         }
4225         if (setLow) {
4226           low = mid + 1;
4227         } else {
4228           high = mid;
4229         }
4230       }
4231       return nativeMin(high, MAX_ARRAY_INDEX);
4232     }
4233
4234     /**
4235      * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
4236      * support for iteratee shorthands.
4237      *
4238      * @private
4239      * @param {Array} array The array to inspect.
4240      * @param {Function} [iteratee] The iteratee invoked per element.
4241      * @returns {Array} Returns the new duplicate free array.
4242      */
4243     function baseSortedUniq(array, iteratee) {
4244       var index = -1,
4245           length = array.length,
4246           resIndex = 0,
4247           result = [];
4248
4249       while (++index < length) {
4250         var value = array[index],
4251             computed = iteratee ? iteratee(value) : value;
4252
4253         if (!index || !eq(computed, seen)) {
4254           var seen = computed;
4255           result[resIndex++] = value === 0 ? 0 : value;
4256         }
4257       }
4258       return result;
4259     }
4260
4261     /**
4262      * The base implementation of `_.toNumber` which doesn't ensure correct
4263      * conversions of binary, hexadecimal, or octal string values.
4264      *
4265      * @private
4266      * @param {*} value The value to process.
4267      * @returns {number} Returns the number.
4268      */
4269     function baseToNumber(value) {
4270       if (typeof value == 'number') {
4271         return value;
4272       }
4273       if (isSymbol(value)) {
4274         return NAN;
4275       }
4276       return +value;
4277     }
4278
4279     /**
4280      * The base implementation of `_.toString` which doesn't convert nullish
4281      * values to empty strings.
4282      *
4283      * @private
4284      * @param {*} value The value to process.
4285      * @returns {string} Returns the string.
4286      */
4287     function baseToString(value) {
4288       // Exit early for strings to avoid a performance hit in some environments.
4289       if (typeof value == 'string') {
4290         return value;
4291       }
4292       if (isArray(value)) {
4293         // Recursively convert values (susceptible to call stack limits).
4294         return arrayMap(value, baseToString) + '';
4295       }
4296       if (isSymbol(value)) {
4297         return symbolToString ? symbolToString.call(value) : '';
4298       }
4299       var result = (value + '');
4300       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
4301     }
4302
4303     /**
4304      * The base implementation of `_.uniqBy` without support for iteratee shorthands.
4305      *
4306      * @private
4307      * @param {Array} array The array to inspect.
4308      * @param {Function} [iteratee] The iteratee invoked per element.
4309      * @param {Function} [comparator] The comparator invoked per element.
4310      * @returns {Array} Returns the new duplicate free array.
4311      */
4312     function baseUniq(array, iteratee, comparator) {
4313       var index = -1,
4314           includes = arrayIncludes,
4315           length = array.length,
4316           isCommon = true,
4317           result = [],
4318           seen = result;
4319
4320       if (comparator) {
4321         isCommon = false;
4322         includes = arrayIncludesWith;
4323       }
4324       else if (length >= LARGE_ARRAY_SIZE) {
4325         var set = iteratee ? null : createSet(array);
4326         if (set) {
4327           return setToArray(set);
4328         }
4329         isCommon = false;
4330         includes = cacheHas;
4331         seen = new SetCache;
4332       }
4333       else {
4334         seen = iteratee ? [] : result;
4335       }
4336       outer:
4337       while (++index < length) {
4338         var value = array[index],
4339             computed = iteratee ? iteratee(value) : value;
4340
4341         value = (comparator || value !== 0) ? value : 0;
4342         if (isCommon && computed === computed) {
4343           var seenIndex = seen.length;
4344           while (seenIndex--) {
4345             if (seen[seenIndex] === computed) {
4346               continue outer;
4347             }
4348           }
4349           if (iteratee) {
4350             seen.push(computed);
4351           }
4352           result.push(value);
4353         }
4354         else if (!includes(seen, computed, comparator)) {
4355           if (seen !== result) {
4356             seen.push(computed);
4357           }
4358           result.push(value);
4359         }
4360       }
4361       return result;
4362     }
4363
4364     /**
4365      * The base implementation of `_.unset`.
4366      *
4367      * @private
4368      * @param {Object} object The object to modify.
4369      * @param {Array|string} path The property path to unset.
4370      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
4371      */
4372     function baseUnset(object, path) {
4373       path = castPath(path, object);
4374       object = parent(object, path);
4375       var key = toKey(last(path));
4376       return !(object != null && hasOwnProperty.call(object, key)) || delete object[key];
4377     }
4378
4379     /**
4380      * The base implementation of `_.update`.
4381      *
4382      * @private
4383      * @param {Object} object The object to modify.
4384      * @param {Array|string} path The path of the property to update.
4385      * @param {Function} updater The function to produce the updated value.
4386      * @param {Function} [customizer] The function to customize path creation.
4387      * @returns {Object} Returns `object`.
4388      */
4389     function baseUpdate(object, path, updater, customizer) {
4390       return baseSet(object, path, updater(baseGet(object, path)), customizer);
4391     }
4392
4393     /**
4394      * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
4395      * without support for iteratee shorthands.
4396      *
4397      * @private
4398      * @param {Array} array The array to query.
4399      * @param {Function} predicate The function invoked per iteration.
4400      * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
4401      * @param {boolean} [fromRight] Specify iterating from right to left.
4402      * @returns {Array} Returns the slice of `array`.
4403      */
4404     function baseWhile(array, predicate, isDrop, fromRight) {
4405       var length = array.length,
4406           index = fromRight ? length : -1;
4407
4408       while ((fromRight ? index-- : ++index < length) &&
4409         predicate(array[index], index, array)) {}
4410
4411       return isDrop
4412         ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
4413         : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
4414     }
4415
4416     /**
4417      * The base implementation of `wrapperValue` which returns the result of
4418      * performing a sequence of actions on the unwrapped `value`, where each
4419      * successive action is supplied the return value of the previous.
4420      *
4421      * @private
4422      * @param {*} value The unwrapped value.
4423      * @param {Array} actions Actions to perform to resolve the unwrapped value.
4424      * @returns {*} Returns the resolved value.
4425      */
4426     function baseWrapperValue(value, actions) {
4427       var result = value;
4428       if (result instanceof LazyWrapper) {
4429         result = result.value();
4430       }
4431       return arrayReduce(actions, function(result, action) {
4432         return action.func.apply(action.thisArg, arrayPush([result], action.args));
4433       }, result);
4434     }
4435
4436     /**
4437      * The base implementation of methods like `_.xor`, without support for
4438      * iteratee shorthands, that accepts an array of arrays to inspect.
4439      *
4440      * @private
4441      * @param {Array} arrays The arrays to inspect.
4442      * @param {Function} [iteratee] The iteratee invoked per element.
4443      * @param {Function} [comparator] The comparator invoked per element.
4444      * @returns {Array} Returns the new array of values.
4445      */
4446     function baseXor(arrays, iteratee, comparator) {
4447       var length = arrays.length;
4448       if (length < 2) {
4449         return length ? baseUniq(arrays[0]) : [];
4450       }
4451       var index = -1,
4452           result = Array(length);
4453
4454       while (++index < length) {
4455         var array = arrays[index],
4456             othIndex = -1;
4457
4458         while (++othIndex < length) {
4459           if (othIndex != index) {
4460             result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
4461           }
4462         }
4463       }
4464       return baseUniq(baseFlatten(result, 1), iteratee, comparator);
4465     }
4466
4467     /**
4468      * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
4469      *
4470      * @private
4471      * @param {Array} props The property identifiers.
4472      * @param {Array} values The property values.
4473      * @param {Function} assignFunc The function to assign values.
4474      * @returns {Object} Returns the new object.
4475      */
4476     function baseZipObject(props, values, assignFunc) {
4477       var index = -1,
4478           length = props.length,
4479           valsLength = values.length,
4480           result = {};
4481
4482       while (++index < length) {
4483         var value = index < valsLength ? values[index] : undefined;
4484         assignFunc(result, props[index], value);
4485       }
4486       return result;
4487     }
4488
4489     /**
4490      * Casts `value` to an empty array if it's not an array like object.
4491      *
4492      * @private
4493      * @param {*} value The value to inspect.
4494      * @returns {Array|Object} Returns the cast array-like object.
4495      */
4496     function castArrayLikeObject(value) {
4497       return isArrayLikeObject(value) ? value : [];
4498     }
4499
4500     /**
4501      * Casts `value` to `identity` if it's not a function.
4502      *
4503      * @private
4504      * @param {*} value The value to inspect.
4505      * @returns {Function} Returns cast function.
4506      */
4507     function castFunction(value) {
4508       return typeof value == 'function' ? value : identity;
4509     }
4510
4511     /**
4512      * Casts `value` to a path array if it's not one.
4513      *
4514      * @private
4515      * @param {*} value The value to inspect.
4516      * @param {Object} [object] The object to query keys on.
4517      * @returns {Array} Returns the cast property path array.
4518      */
4519     function castPath(value, object) {
4520       if (isArray(value)) {
4521         return value;
4522       }
4523       return isKey(value, object) ? [value] : stringToPath(toString(value));
4524     }
4525
4526     /**
4527      * A `baseRest` alias which can be replaced with `identity` by module
4528      * replacement plugins.
4529      *
4530      * @private
4531      * @type {Function}
4532      * @param {Function} func The function to apply a rest parameter to.
4533      * @returns {Function} Returns the new function.
4534      */
4535     var castRest = baseRest;
4536
4537     /**
4538      * Casts `array` to a slice if it's needed.
4539      *
4540      * @private
4541      * @param {Array} array The array to inspect.
4542      * @param {number} start The start position.
4543      * @param {number} [end=array.length] The end position.
4544      * @returns {Array} Returns the cast slice.
4545      */
4546     function castSlice(array, start, end) {
4547       var length = array.length;
4548       end = end === undefined ? length : end;
4549       return (!start && end >= length) ? array : baseSlice(array, start, end);
4550     }
4551
4552     /**
4553      * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
4554      *
4555      * @private
4556      * @param {number|Object} id The timer id or timeout object of the timer to clear.
4557      */
4558     var clearTimeout = ctxClearTimeout || function(id) {
4559       return root.clearTimeout(id);
4560     };
4561
4562     /**
4563      * Creates a clone of  `buffer`.
4564      *
4565      * @private
4566      * @param {Buffer} buffer The buffer to clone.
4567      * @param {boolean} [isDeep] Specify a deep clone.
4568      * @returns {Buffer} Returns the cloned buffer.
4569      */
4570     function cloneBuffer(buffer, isDeep) {
4571       if (isDeep) {
4572         return buffer.slice();
4573       }
4574       var length = buffer.length,
4575           result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
4576
4577       buffer.copy(result);
4578       return result;
4579     }
4580
4581     /**
4582      * Creates a clone of `arrayBuffer`.
4583      *
4584      * @private
4585      * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
4586      * @returns {ArrayBuffer} Returns the cloned array buffer.
4587      */
4588     function cloneArrayBuffer(arrayBuffer) {
4589       var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
4590       new Uint8Array(result).set(new Uint8Array(arrayBuffer));
4591       return result;
4592     }
4593
4594     /**
4595      * Creates a clone of `dataView`.
4596      *
4597      * @private
4598      * @param {Object} dataView The data view to clone.
4599      * @param {boolean} [isDeep] Specify a deep clone.
4600      * @returns {Object} Returns the cloned data view.
4601      */
4602     function cloneDataView(dataView, isDeep) {
4603       var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
4604       return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
4605     }
4606
4607     /**
4608      * Creates a clone of `map`.
4609      *
4610      * @private
4611      * @param {Object} map The map to clone.
4612      * @param {Function} cloneFunc The function to clone values.
4613      * @param {boolean} [isDeep] Specify a deep clone.
4614      * @returns {Object} Returns the cloned map.
4615      */
4616     function cloneMap(map, isDeep, cloneFunc) {
4617       var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
4618       return arrayReduce(array, addMapEntry, new map.constructor);
4619     }
4620
4621     /**
4622      * Creates a clone of `regexp`.
4623      *
4624      * @private
4625      * @param {Object} regexp The regexp to clone.
4626      * @returns {Object} Returns the cloned regexp.
4627      */
4628     function cloneRegExp(regexp) {
4629       var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
4630       result.lastIndex = regexp.lastIndex;
4631       return result;
4632     }
4633
4634     /**
4635      * Creates a clone of `set`.
4636      *
4637      * @private
4638      * @param {Object} set The set to clone.
4639      * @param {Function} cloneFunc The function to clone values.
4640      * @param {boolean} [isDeep] Specify a deep clone.
4641      * @returns {Object} Returns the cloned set.
4642      */
4643     function cloneSet(set, isDeep, cloneFunc) {
4644       var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
4645       return arrayReduce(array, addSetEntry, new set.constructor);
4646     }
4647
4648     /**
4649      * Creates a clone of the `symbol` object.
4650      *
4651      * @private
4652      * @param {Object} symbol The symbol object to clone.
4653      * @returns {Object} Returns the cloned symbol object.
4654      */
4655     function cloneSymbol(symbol) {
4656       return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
4657     }
4658
4659     /**
4660      * Creates a clone of `typedArray`.
4661      *
4662      * @private
4663      * @param {Object} typedArray The typed array to clone.
4664      * @param {boolean} [isDeep] Specify a deep clone.
4665      * @returns {Object} Returns the cloned typed array.
4666      */
4667     function cloneTypedArray(typedArray, isDeep) {
4668       var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
4669       return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
4670     }
4671
4672     /**
4673      * Compares values to sort them in ascending order.
4674      *
4675      * @private
4676      * @param {*} value The value to compare.
4677      * @param {*} other The other value to compare.
4678      * @returns {number} Returns the sort order indicator for `value`.
4679      */
4680     function compareAscending(value, other) {
4681       if (value !== other) {
4682         var valIsDefined = value !== undefined,
4683             valIsNull = value === null,
4684             valIsReflexive = value === value,
4685             valIsSymbol = isSymbol(value);
4686
4687         var othIsDefined = other !== undefined,
4688             othIsNull = other === null,
4689             othIsReflexive = other === other,
4690             othIsSymbol = isSymbol(other);
4691
4692         if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
4693             (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
4694             (valIsNull && othIsDefined && othIsReflexive) ||
4695             (!valIsDefined && othIsReflexive) ||
4696             !valIsReflexive) {
4697           return 1;
4698         }
4699         if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
4700             (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
4701             (othIsNull && valIsDefined && valIsReflexive) ||
4702             (!othIsDefined && valIsReflexive) ||
4703             !othIsReflexive) {
4704           return -1;
4705         }
4706       }
4707       return 0;
4708     }
4709
4710     /**
4711      * Used by `_.orderBy` to compare multiple properties of a value to another
4712      * and stable sort them.
4713      *
4714      * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
4715      * specify an order of "desc" for descending or "asc" for ascending sort order
4716      * of corresponding values.
4717      *
4718      * @private
4719      * @param {Object} object The object to compare.
4720      * @param {Object} other The other object to compare.
4721      * @param {boolean[]|string[]} orders The order to sort by for each property.
4722      * @returns {number} Returns the sort order indicator for `object`.
4723      */
4724     function compareMultiple(object, other, orders) {
4725       var index = -1,
4726           objCriteria = object.criteria,
4727           othCriteria = other.criteria,
4728           length = objCriteria.length,
4729           ordersLength = orders.length;
4730
4731       while (++index < length) {
4732         var result = compareAscending(objCriteria[index], othCriteria[index]);
4733         if (result) {
4734           if (index >= ordersLength) {
4735             return result;
4736           }
4737           var order = orders[index];
4738           return result * (order == 'desc' ? -1 : 1);
4739         }
4740       }
4741       // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
4742       // that causes it, under certain circumstances, to provide the same value for
4743       // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
4744       // for more details.
4745       //
4746       // This also ensures a stable sort in V8 and other engines.
4747       // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
4748       return object.index - other.index;
4749     }
4750
4751     /**
4752      * Creates an array that is the composition of partially applied arguments,
4753      * placeholders, and provided arguments into a single array of arguments.
4754      *
4755      * @private
4756      * @param {Array} args The provided arguments.
4757      * @param {Array} partials The arguments to prepend to those provided.
4758      * @param {Array} holders The `partials` placeholder indexes.
4759      * @params {boolean} [isCurried] Specify composing for a curried function.
4760      * @returns {Array} Returns the new array of composed arguments.
4761      */
4762     function composeArgs(args, partials, holders, isCurried) {
4763       var argsIndex = -1,
4764           argsLength = args.length,
4765           holdersLength = holders.length,
4766           leftIndex = -1,
4767           leftLength = partials.length,
4768           rangeLength = nativeMax(argsLength - holdersLength, 0),
4769           result = Array(leftLength + rangeLength),
4770           isUncurried = !isCurried;
4771
4772       while (++leftIndex < leftLength) {
4773         result[leftIndex] = partials[leftIndex];
4774       }
4775       while (++argsIndex < holdersLength) {
4776         if (isUncurried || argsIndex < argsLength) {
4777           result[holders[argsIndex]] = args[argsIndex];
4778         }
4779       }
4780       while (rangeLength--) {
4781         result[leftIndex++] = args[argsIndex++];
4782       }
4783       return result;
4784     }
4785
4786     /**
4787      * This function is like `composeArgs` except that the arguments composition
4788      * is tailored for `_.partialRight`.
4789      *
4790      * @private
4791      * @param {Array} args The provided arguments.
4792      * @param {Array} partials The arguments to append to those provided.
4793      * @param {Array} holders The `partials` placeholder indexes.
4794      * @params {boolean} [isCurried] Specify composing for a curried function.
4795      * @returns {Array} Returns the new array of composed arguments.
4796      */
4797     function composeArgsRight(args, partials, holders, isCurried) {
4798       var argsIndex = -1,
4799           argsLength = args.length,
4800           holdersIndex = -1,
4801           holdersLength = holders.length,
4802           rightIndex = -1,
4803           rightLength = partials.length,
4804           rangeLength = nativeMax(argsLength - holdersLength, 0),
4805           result = Array(rangeLength + rightLength),
4806           isUncurried = !isCurried;
4807
4808       while (++argsIndex < rangeLength) {
4809         result[argsIndex] = args[argsIndex];
4810       }
4811       var offset = argsIndex;
4812       while (++rightIndex < rightLength) {
4813         result[offset + rightIndex] = partials[rightIndex];
4814       }
4815       while (++holdersIndex < holdersLength) {
4816         if (isUncurried || argsIndex < argsLength) {
4817           result[offset + holders[holdersIndex]] = args[argsIndex++];
4818         }
4819       }
4820       return result;
4821     }
4822
4823     /**
4824      * Copies the values of `source` to `array`.
4825      *
4826      * @private
4827      * @param {Array} source The array to copy values from.
4828      * @param {Array} [array=[]] The array to copy values to.
4829      * @returns {Array} Returns `array`.
4830      */
4831     function copyArray(source, array) {
4832       var index = -1,
4833           length = source.length;
4834
4835       array || (array = Array(length));
4836       while (++index < length) {
4837         array[index] = source[index];
4838       }
4839       return array;
4840     }
4841
4842     /**
4843      * Copies properties of `source` to `object`.
4844      *
4845      * @private
4846      * @param {Object} source The object to copy properties from.
4847      * @param {Array} props The property identifiers to copy.
4848      * @param {Object} [object={}] The object to copy properties to.
4849      * @param {Function} [customizer] The function to customize copied values.
4850      * @returns {Object} Returns `object`.
4851      */
4852     function copyObject(source, props, object, customizer) {
4853       var isNew = !object;
4854       object || (object = {});
4855
4856       var index = -1,
4857           length = props.length;
4858
4859       while (++index < length) {
4860         var key = props[index];
4861
4862         var newValue = customizer
4863           ? customizer(object[key], source[key], key, object, source)
4864           : undefined;
4865
4866         if (newValue === undefined) {
4867           newValue = source[key];
4868         }
4869         if (isNew) {
4870           baseAssignValue(object, key, newValue);
4871         } else {
4872           assignValue(object, key, newValue);
4873         }
4874       }
4875       return object;
4876     }
4877
4878     /**
4879      * Copies own symbols of `source` to `object`.
4880      *
4881      * @private
4882      * @param {Object} source The object to copy symbols from.
4883      * @param {Object} [object={}] The object to copy symbols to.
4884      * @returns {Object} Returns `object`.
4885      */
4886     function copySymbols(source, object) {
4887       return copyObject(source, getSymbols(source), object);
4888     }
4889
4890     /**
4891      * Copies own and inherited symbols of `source` to `object`.
4892      *
4893      * @private
4894      * @param {Object} source The object to copy symbols from.
4895      * @param {Object} [object={}] The object to copy symbols to.
4896      * @returns {Object} Returns `object`.
4897      */
4898     function copySymbolsIn(source, object) {
4899       return copyObject(source, getSymbolsIn(source), object);
4900     }
4901
4902     /**
4903      * Creates a function like `_.groupBy`.
4904      *
4905      * @private
4906      * @param {Function} setter The function to set accumulator values.
4907      * @param {Function} [initializer] The accumulator object initializer.
4908      * @returns {Function} Returns the new aggregator function.
4909      */
4910     function createAggregator(setter, initializer) {
4911       return function(collection, iteratee) {
4912         var func = isArray(collection) ? arrayAggregator : baseAggregator,
4913             accumulator = initializer ? initializer() : {};
4914
4915         return func(collection, setter, getIteratee(iteratee, 2), accumulator);
4916       };
4917     }
4918
4919     /**
4920      * Creates a function like `_.assign`.
4921      *
4922      * @private
4923      * @param {Function} assigner The function to assign values.
4924      * @returns {Function} Returns the new assigner function.
4925      */
4926     function createAssigner(assigner) {
4927       return baseRest(function(object, sources) {
4928         var index = -1,
4929             length = sources.length,
4930             customizer = length > 1 ? sources[length - 1] : undefined,
4931             guard = length > 2 ? sources[2] : undefined;
4932
4933         customizer = (assigner.length > 3 && typeof customizer == 'function')
4934           ? (length--, customizer)
4935           : undefined;
4936
4937         if (guard && isIterateeCall(sources[0], sources[1], guard)) {
4938           customizer = length < 3 ? undefined : customizer;
4939           length = 1;
4940         }
4941         object = Object(object);
4942         while (++index < length) {
4943           var source = sources[index];
4944           if (source) {
4945             assigner(object, source, index, customizer);
4946           }
4947         }
4948         return object;
4949       });
4950     }
4951
4952     /**
4953      * Creates a `baseEach` or `baseEachRight` function.
4954      *
4955      * @private
4956      * @param {Function} eachFunc The function to iterate over a collection.
4957      * @param {boolean} [fromRight] Specify iterating from right to left.
4958      * @returns {Function} Returns the new base function.
4959      */
4960     function createBaseEach(eachFunc, fromRight) {
4961       return function(collection, iteratee) {
4962         if (collection == null) {
4963           return collection;
4964         }
4965         if (!isArrayLike(collection)) {
4966           return eachFunc(collection, iteratee);
4967         }
4968         var length = collection.length,
4969             index = fromRight ? length : -1,
4970             iterable = Object(collection);
4971
4972         while ((fromRight ? index-- : ++index < length)) {
4973           if (iteratee(iterable[index], index, iterable) === false) {
4974             break;
4975           }
4976         }
4977         return collection;
4978       };
4979     }
4980
4981     /**
4982      * Creates a base function for methods like `_.forIn` and `_.forOwn`.
4983      *
4984      * @private
4985      * @param {boolean} [fromRight] Specify iterating from right to left.
4986      * @returns {Function} Returns the new base function.
4987      */
4988     function createBaseFor(fromRight) {
4989       return function(object, iteratee, keysFunc) {
4990         var index = -1,
4991             iterable = Object(object),
4992             props = keysFunc(object),
4993             length = props.length;
4994
4995         while (length--) {
4996           var key = props[fromRight ? length : ++index];
4997           if (iteratee(iterable[key], key, iterable) === false) {
4998             break;
4999           }
5000         }
5001         return object;
5002       };
5003     }
5004
5005     /**
5006      * Creates a function that wraps `func` to invoke it with the optional `this`
5007      * binding of `thisArg`.
5008      *
5009      * @private
5010      * @param {Function} func The function to wrap.
5011      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5012      * @param {*} [thisArg] The `this` binding of `func`.
5013      * @returns {Function} Returns the new wrapped function.
5014      */
5015     function createBind(func, bitmask, thisArg) {
5016       var isBind = bitmask & WRAP_BIND_FLAG,
5017           Ctor = createCtor(func);
5018
5019       function wrapper() {
5020         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5021         return fn.apply(isBind ? thisArg : this, arguments);
5022       }
5023       return wrapper;
5024     }
5025
5026     /**
5027      * Creates a function like `_.lowerFirst`.
5028      *
5029      * @private
5030      * @param {string} methodName The name of the `String` case method to use.
5031      * @returns {Function} Returns the new case function.
5032      */
5033     function createCaseFirst(methodName) {
5034       return function(string) {
5035         string = toString(string);
5036
5037         var strSymbols = hasUnicode(string)
5038           ? stringToArray(string)
5039           : undefined;
5040
5041         var chr = strSymbols
5042           ? strSymbols[0]
5043           : string.charAt(0);
5044
5045         var trailing = strSymbols
5046           ? castSlice(strSymbols, 1).join('')
5047           : string.slice(1);
5048
5049         return chr[methodName]() + trailing;
5050       };
5051     }
5052
5053     /**
5054      * Creates a function like `_.camelCase`.
5055      *
5056      * @private
5057      * @param {Function} callback The function to combine each word.
5058      * @returns {Function} Returns the new compounder function.
5059      */
5060     function createCompounder(callback) {
5061       return function(string) {
5062         return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
5063       };
5064     }
5065
5066     /**
5067      * Creates a function that produces an instance of `Ctor` regardless of
5068      * whether it was invoked as part of a `new` expression or by `call` or `apply`.
5069      *
5070      * @private
5071      * @param {Function} Ctor The constructor to wrap.
5072      * @returns {Function} Returns the new wrapped function.
5073      */
5074     function createCtor(Ctor) {
5075       return function() {
5076         // Use a `switch` statement to work with class constructors. See
5077         // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
5078         // for more details.
5079         var args = arguments;
5080         switch (args.length) {
5081           case 0: return new Ctor;
5082           case 1: return new Ctor(args[0]);
5083           case 2: return new Ctor(args[0], args[1]);
5084           case 3: return new Ctor(args[0], args[1], args[2]);
5085           case 4: return new Ctor(args[0], args[1], args[2], args[3]);
5086           case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
5087           case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
5088           case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
5089         }
5090         var thisBinding = baseCreate(Ctor.prototype),
5091             result = Ctor.apply(thisBinding, args);
5092
5093         // Mimic the constructor's `return` behavior.
5094         // See https://es5.github.io/#x13.2.2 for more details.
5095         return isObject(result) ? result : thisBinding;
5096       };
5097     }
5098
5099     /**
5100      * Creates a function that wraps `func` to enable currying.
5101      *
5102      * @private
5103      * @param {Function} func The function to wrap.
5104      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5105      * @param {number} arity The arity of `func`.
5106      * @returns {Function} Returns the new wrapped function.
5107      */
5108     function createCurry(func, bitmask, arity) {
5109       var Ctor = createCtor(func);
5110
5111       function wrapper() {
5112         var length = arguments.length,
5113             args = Array(length),
5114             index = length,
5115             placeholder = getHolder(wrapper);
5116
5117         while (index--) {
5118           args[index] = arguments[index];
5119         }
5120         var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
5121           ? []
5122           : replaceHolders(args, placeholder);
5123
5124         length -= holders.length;
5125         if (length < arity) {
5126           return createRecurry(
5127             func, bitmask, createHybrid, wrapper.placeholder, undefined,
5128             args, holders, undefined, undefined, arity - length);
5129         }
5130         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5131         return apply(fn, this, args);
5132       }
5133       return wrapper;
5134     }
5135
5136     /**
5137      * Creates a `_.find` or `_.findLast` function.
5138      *
5139      * @private
5140      * @param {Function} findIndexFunc The function to find the collection index.
5141      * @returns {Function} Returns the new find function.
5142      */
5143     function createFind(findIndexFunc) {
5144       return function(collection, predicate, fromIndex) {
5145         var iterable = Object(collection);
5146         if (!isArrayLike(collection)) {
5147           var iteratee = getIteratee(predicate, 3);
5148           collection = keys(collection);
5149           predicate = function(key) { return iteratee(iterable[key], key, iterable); };
5150         }
5151         var index = findIndexFunc(collection, predicate, fromIndex);
5152         return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
5153       };
5154     }
5155
5156     /**
5157      * Creates a `_.flow` or `_.flowRight` function.
5158      *
5159      * @private
5160      * @param {boolean} [fromRight] Specify iterating from right to left.
5161      * @returns {Function} Returns the new flow function.
5162      */
5163     function createFlow(fromRight) {
5164       return flatRest(function(funcs) {
5165         var length = funcs.length,
5166             index = length,
5167             prereq = LodashWrapper.prototype.thru;
5168
5169         if (fromRight) {
5170           funcs.reverse();
5171         }
5172         while (index--) {
5173           var func = funcs[index];
5174           if (typeof func != 'function') {
5175             throw new TypeError(FUNC_ERROR_TEXT);
5176           }
5177           if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
5178             var wrapper = new LodashWrapper([], true);
5179           }
5180         }
5181         index = wrapper ? index : length;
5182         while (++index < length) {
5183           func = funcs[index];
5184
5185           var funcName = getFuncName(func),
5186               data = funcName == 'wrapper' ? getData(func) : undefined;
5187
5188           if (data && isLaziable(data[0]) &&
5189                 data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
5190                 !data[4].length && data[9] == 1
5191               ) {
5192             wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
5193           } else {
5194             wrapper = (func.length == 1 && isLaziable(func))
5195               ? wrapper[funcName]()
5196               : wrapper.thru(func);
5197           }
5198         }
5199         return function() {
5200           var args = arguments,
5201               value = args[0];
5202
5203           if (wrapper && args.length == 1 &&
5204               isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
5205             return wrapper.plant(value).value();
5206           }
5207           var index = 0,
5208               result = length ? funcs[index].apply(this, args) : value;
5209
5210           while (++index < length) {
5211             result = funcs[index].call(this, result);
5212           }
5213           return result;
5214         };
5215       });
5216     }
5217
5218     /**
5219      * Creates a function that wraps `func` to invoke it with optional `this`
5220      * binding of `thisArg`, partial application, and currying.
5221      *
5222      * @private
5223      * @param {Function|string} func The function or method name to wrap.
5224      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5225      * @param {*} [thisArg] The `this` binding of `func`.
5226      * @param {Array} [partials] The arguments to prepend to those provided to
5227      *  the new function.
5228      * @param {Array} [holders] The `partials` placeholder indexes.
5229      * @param {Array} [partialsRight] The arguments to append to those provided
5230      *  to the new function.
5231      * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
5232      * @param {Array} [argPos] The argument positions of the new function.
5233      * @param {number} [ary] The arity cap of `func`.
5234      * @param {number} [arity] The arity of `func`.
5235      * @returns {Function} Returns the new wrapped function.
5236      */
5237     function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
5238       var isAry = bitmask & WRAP_ARY_FLAG,
5239           isBind = bitmask & WRAP_BIND_FLAG,
5240           isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
5241           isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
5242           isFlip = bitmask & WRAP_FLIP_FLAG,
5243           Ctor = isBindKey ? undefined : createCtor(func);
5244
5245       function wrapper() {
5246         var length = arguments.length,
5247             args = Array(length),
5248             index = length;
5249
5250         while (index--) {
5251           args[index] = arguments[index];
5252         }
5253         if (isCurried) {
5254           var placeholder = getHolder(wrapper),
5255               holdersCount = countHolders(args, placeholder);
5256         }
5257         if (partials) {
5258           args = composeArgs(args, partials, holders, isCurried);
5259         }
5260         if (partialsRight) {
5261           args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
5262         }
5263         length -= holdersCount;
5264         if (isCurried && length < arity) {
5265           var newHolders = replaceHolders(args, placeholder);
5266           return createRecurry(
5267             func, bitmask, createHybrid, wrapper.placeholder, thisArg,
5268             args, newHolders, argPos, ary, arity - length
5269           );
5270         }
5271         var thisBinding = isBind ? thisArg : this,
5272             fn = isBindKey ? thisBinding[func] : func;
5273
5274         length = args.length;
5275         if (argPos) {
5276           args = reorder(args, argPos);
5277         } else if (isFlip && length > 1) {
5278           args.reverse();
5279         }
5280         if (isAry && ary < length) {
5281           args.length = ary;
5282         }
5283         if (this && this !== root && this instanceof wrapper) {
5284           fn = Ctor || createCtor(fn);
5285         }
5286         return fn.apply(thisBinding, args);
5287       }
5288       return wrapper;
5289     }
5290
5291     /**
5292      * Creates a function like `_.invertBy`.
5293      *
5294      * @private
5295      * @param {Function} setter The function to set accumulator values.
5296      * @param {Function} toIteratee The function to resolve iteratees.
5297      * @returns {Function} Returns the new inverter function.
5298      */
5299     function createInverter(setter, toIteratee) {
5300       return function(object, iteratee) {
5301         return baseInverter(object, setter, toIteratee(iteratee), {});
5302       };
5303     }
5304
5305     /**
5306      * Creates a function that performs a mathematical operation on two values.
5307      *
5308      * @private
5309      * @param {Function} operator The function to perform the operation.
5310      * @param {number} [defaultValue] The value used for `undefined` arguments.
5311      * @returns {Function} Returns the new mathematical operation function.
5312      */
5313     function createMathOperation(operator, defaultValue) {
5314       return function(value, other) {
5315         var result;
5316         if (value === undefined && other === undefined) {
5317           return defaultValue;
5318         }
5319         if (value !== undefined) {
5320           result = value;
5321         }
5322         if (other !== undefined) {
5323           if (result === undefined) {
5324             return other;
5325           }
5326           if (typeof value == 'string' || typeof other == 'string') {
5327             value = baseToString(value);
5328             other = baseToString(other);
5329           } else {
5330             value = baseToNumber(value);
5331             other = baseToNumber(other);
5332           }
5333           result = operator(value, other);
5334         }
5335         return result;
5336       };
5337     }
5338
5339     /**
5340      * Creates a function like `_.over`.
5341      *
5342      * @private
5343      * @param {Function} arrayFunc The function to iterate over iteratees.
5344      * @returns {Function} Returns the new over function.
5345      */
5346     function createOver(arrayFunc) {
5347       return flatRest(function(iteratees) {
5348         iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
5349         return baseRest(function(args) {
5350           var thisArg = this;
5351           return arrayFunc(iteratees, function(iteratee) {
5352             return apply(iteratee, thisArg, args);
5353           });
5354         });
5355       });
5356     }
5357
5358     /**
5359      * Creates the padding for `string` based on `length`. The `chars` string
5360      * is truncated if the number of characters exceeds `length`.
5361      *
5362      * @private
5363      * @param {number} length The padding length.
5364      * @param {string} [chars=' '] The string used as padding.
5365      * @returns {string} Returns the padding for `string`.
5366      */
5367     function createPadding(length, chars) {
5368       chars = chars === undefined ? ' ' : baseToString(chars);
5369
5370       var charsLength = chars.length;
5371       if (charsLength < 2) {
5372         return charsLength ? baseRepeat(chars, length) : chars;
5373       }
5374       var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
5375       return hasUnicode(chars)
5376         ? castSlice(stringToArray(result), 0, length).join('')
5377         : result.slice(0, length);
5378     }
5379
5380     /**
5381      * Creates a function that wraps `func` to invoke it with the `this` binding
5382      * of `thisArg` and `partials` prepended to the arguments it receives.
5383      *
5384      * @private
5385      * @param {Function} func The function to wrap.
5386      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5387      * @param {*} thisArg The `this` binding of `func`.
5388      * @param {Array} partials The arguments to prepend to those provided to
5389      *  the new function.
5390      * @returns {Function} Returns the new wrapped function.
5391      */
5392     function createPartial(func, bitmask, thisArg, partials) {
5393       var isBind = bitmask & WRAP_BIND_FLAG,
5394           Ctor = createCtor(func);
5395
5396       function wrapper() {
5397         var argsIndex = -1,
5398             argsLength = arguments.length,
5399             leftIndex = -1,
5400             leftLength = partials.length,
5401             args = Array(leftLength + argsLength),
5402             fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5403
5404         while (++leftIndex < leftLength) {
5405           args[leftIndex] = partials[leftIndex];
5406         }
5407         while (argsLength--) {
5408           args[leftIndex++] = arguments[++argsIndex];
5409         }
5410         return apply(fn, isBind ? thisArg : this, args);
5411       }
5412       return wrapper;
5413     }
5414
5415     /**
5416      * Creates a `_.range` or `_.rangeRight` function.
5417      *
5418      * @private
5419      * @param {boolean} [fromRight] Specify iterating from right to left.
5420      * @returns {Function} Returns the new range function.
5421      */
5422     function createRange(fromRight) {
5423       return function(start, end, step) {
5424         if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
5425           end = step = undefined;
5426         }
5427         // Ensure the sign of `-0` is preserved.
5428         start = toFinite(start);
5429         if (end === undefined) {
5430           end = start;
5431           start = 0;
5432         } else {
5433           end = toFinite(end);
5434         }
5435         step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
5436         return baseRange(start, end, step, fromRight);
5437       };
5438     }
5439
5440     /**
5441      * Creates a function that performs a relational operation on two values.
5442      *
5443      * @private
5444      * @param {Function} operator The function to perform the operation.
5445      * @returns {Function} Returns the new relational operation function.
5446      */
5447     function createRelationalOperation(operator) {
5448       return function(value, other) {
5449         if (!(typeof value == 'string' && typeof other == 'string')) {
5450           value = toNumber(value);
5451           other = toNumber(other);
5452         }
5453         return operator(value, other);
5454       };
5455     }
5456
5457     /**
5458      * Creates a function that wraps `func` to continue currying.
5459      *
5460      * @private
5461      * @param {Function} func The function to wrap.
5462      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5463      * @param {Function} wrapFunc The function to create the `func` wrapper.
5464      * @param {*} placeholder The placeholder value.
5465      * @param {*} [thisArg] The `this` binding of `func`.
5466      * @param {Array} [partials] The arguments to prepend to those provided to
5467      *  the new function.
5468      * @param {Array} [holders] The `partials` placeholder indexes.
5469      * @param {Array} [argPos] The argument positions of the new function.
5470      * @param {number} [ary] The arity cap of `func`.
5471      * @param {number} [arity] The arity of `func`.
5472      * @returns {Function} Returns the new wrapped function.
5473      */
5474     function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
5475       var isCurry = bitmask & WRAP_CURRY_FLAG,
5476           newHolders = isCurry ? holders : undefined,
5477           newHoldersRight = isCurry ? undefined : holders,
5478           newPartials = isCurry ? partials : undefined,
5479           newPartialsRight = isCurry ? undefined : partials;
5480
5481       bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
5482       bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
5483
5484       if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
5485         bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
5486       }
5487       var newData = [
5488         func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
5489         newHoldersRight, argPos, ary, arity
5490       ];
5491
5492       var result = wrapFunc.apply(undefined, newData);
5493       if (isLaziable(func)) {
5494         setData(result, newData);
5495       }
5496       result.placeholder = placeholder;
5497       return setWrapToString(result, func, bitmask);
5498     }
5499
5500     /**
5501      * Creates a function like `_.round`.
5502      *
5503      * @private
5504      * @param {string} methodName The name of the `Math` method to use when rounding.
5505      * @returns {Function} Returns the new round function.
5506      */
5507     function createRound(methodName) {
5508       var func = Math[methodName];
5509       return function(number, precision) {
5510         number = toNumber(number);
5511         precision = nativeMin(toInteger(precision), 292);
5512         if (precision) {
5513           // Shift with exponential notation to avoid floating-point issues.
5514           // See [MDN](https://mdn.io/round#Examples) for more details.
5515           var pair = (toString(number) + 'e').split('e'),
5516               value = func(pair[0] + 'e' + (+pair[1] + precision));
5517
5518           pair = (toString(value) + 'e').split('e');
5519           return +(pair[0] + 'e' + (+pair[1] - precision));
5520         }
5521         return func(number);
5522       };
5523     }
5524
5525     /**
5526      * Creates a set object of `values`.
5527      *
5528      * @private
5529      * @param {Array} values The values to add to the set.
5530      * @returns {Object} Returns the new set.
5531      */
5532     var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
5533       return new Set(values);
5534     };
5535
5536     /**
5537      * Creates a `_.toPairs` or `_.toPairsIn` function.
5538      *
5539      * @private
5540      * @param {Function} keysFunc The function to get the keys of a given object.
5541      * @returns {Function} Returns the new pairs function.
5542      */
5543     function createToPairs(keysFunc) {
5544       return function(object) {
5545         var tag = getTag(object);
5546         if (tag == mapTag) {
5547           return mapToArray(object);
5548         }
5549         if (tag == setTag) {
5550           return setToPairs(object);
5551         }
5552         return baseToPairs(object, keysFunc(object));
5553       };
5554     }
5555
5556     /**
5557      * Creates a function that either curries or invokes `func` with optional
5558      * `this` binding and partially applied arguments.
5559      *
5560      * @private
5561      * @param {Function|string} func The function or method name to wrap.
5562      * @param {number} bitmask The bitmask flags.
5563      *    1 - `_.bind`
5564      *    2 - `_.bindKey`
5565      *    4 - `_.curry` or `_.curryRight` of a bound function
5566      *    8 - `_.curry`
5567      *   16 - `_.curryRight`
5568      *   32 - `_.partial`
5569      *   64 - `_.partialRight`
5570      *  128 - `_.rearg`
5571      *  256 - `_.ary`
5572      *  512 - `_.flip`
5573      * @param {*} [thisArg] The `this` binding of `func`.
5574      * @param {Array} [partials] The arguments to be partially applied.
5575      * @param {Array} [holders] The `partials` placeholder indexes.
5576      * @param {Array} [argPos] The argument positions of the new function.
5577      * @param {number} [ary] The arity cap of `func`.
5578      * @param {number} [arity] The arity of `func`.
5579      * @returns {Function} Returns the new wrapped function.
5580      */
5581     function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
5582       var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
5583       if (!isBindKey && typeof func != 'function') {
5584         throw new TypeError(FUNC_ERROR_TEXT);
5585       }
5586       var length = partials ? partials.length : 0;
5587       if (!length) {
5588         bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
5589         partials = holders = undefined;
5590       }
5591       ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
5592       arity = arity === undefined ? arity : toInteger(arity);
5593       length -= holders ? holders.length : 0;
5594
5595       if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
5596         var partialsRight = partials,
5597             holdersRight = holders;
5598
5599         partials = holders = undefined;
5600       }
5601       var data = isBindKey ? undefined : getData(func);
5602
5603       var newData = [
5604         func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
5605         argPos, ary, arity
5606       ];
5607
5608       if (data) {
5609         mergeData(newData, data);
5610       }
5611       func = newData[0];
5612       bitmask = newData[1];
5613       thisArg = newData[2];
5614       partials = newData[3];
5615       holders = newData[4];
5616       arity = newData[9] = newData[9] == null
5617         ? (isBindKey ? 0 : func.length)
5618         : nativeMax(newData[9] - length, 0);
5619
5620       if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
5621         bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
5622       }
5623       if (!bitmask || bitmask == WRAP_BIND_FLAG) {
5624         var result = createBind(func, bitmask, thisArg);
5625       } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
5626         result = createCurry(func, bitmask, arity);
5627       } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
5628         result = createPartial(func, bitmask, thisArg, partials);
5629       } else {
5630         result = createHybrid.apply(undefined, newData);
5631       }
5632       var setter = data ? baseSetData : setData;
5633       return setWrapToString(setter(result, newData), func, bitmask);
5634     }
5635
5636     /**
5637      * A specialized version of `baseIsEqualDeep` for arrays with support for
5638      * partial deep comparisons.
5639      *
5640      * @private
5641      * @param {Array} array The array to compare.
5642      * @param {Array} other The other array to compare.
5643      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5644      * @param {Function} customizer The function to customize comparisons.
5645      * @param {Function} equalFunc The function to determine equivalents of values.
5646      * @param {Object} stack Tracks traversed `array` and `other` objects.
5647      * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
5648      */
5649     function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
5650       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5651           arrLength = array.length,
5652           othLength = other.length;
5653
5654       if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
5655         return false;
5656       }
5657       // Assume cyclic values are equal.
5658       var stacked = stack.get(array);
5659       if (stacked && stack.get(other)) {
5660         return stacked == other;
5661       }
5662       var index = -1,
5663           result = true,
5664           seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
5665
5666       stack.set(array, other);
5667       stack.set(other, array);
5668
5669       // Ignore non-index properties.
5670       while (++index < arrLength) {
5671         var arrValue = array[index],
5672             othValue = other[index];
5673
5674         if (customizer) {
5675           var compared = isPartial
5676             ? customizer(othValue, arrValue, index, other, array, stack)
5677             : customizer(arrValue, othValue, index, array, other, stack);
5678         }
5679         if (compared !== undefined) {
5680           if (compared) {
5681             continue;
5682           }
5683           result = false;
5684           break;
5685         }
5686         // Recursively compare arrays (susceptible to call stack limits).
5687         if (seen) {
5688           if (!arraySome(other, function(othValue, othIndex) {
5689                 if (!cacheHas(seen, othIndex) &&
5690                     (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
5691                   return seen.push(othIndex);
5692                 }
5693               })) {
5694             result = false;
5695             break;
5696           }
5697         } else if (!(
5698               arrValue === othValue ||
5699                 equalFunc(arrValue, othValue, bitmask, customizer, stack)
5700             )) {
5701           result = false;
5702           break;
5703         }
5704       }
5705       stack['delete'](array);
5706       stack['delete'](other);
5707       return result;
5708     }
5709
5710     /**
5711      * A specialized version of `baseIsEqualDeep` for comparing objects of
5712      * the same `toStringTag`.
5713      *
5714      * **Note:** This function only supports comparing values with tags of
5715      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
5716      *
5717      * @private
5718      * @param {Object} object The object to compare.
5719      * @param {Object} other The other object to compare.
5720      * @param {string} tag The `toStringTag` of the objects to compare.
5721      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5722      * @param {Function} customizer The function to customize comparisons.
5723      * @param {Function} equalFunc The function to determine equivalents of values.
5724      * @param {Object} stack Tracks traversed `object` and `other` objects.
5725      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5726      */
5727     function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
5728       switch (tag) {
5729         case dataViewTag:
5730           if ((object.byteLength != other.byteLength) ||
5731               (object.byteOffset != other.byteOffset)) {
5732             return false;
5733           }
5734           object = object.buffer;
5735           other = other.buffer;
5736
5737         case arrayBufferTag:
5738           if ((object.byteLength != other.byteLength) ||
5739               !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
5740             return false;
5741           }
5742           return true;
5743
5744         case boolTag:
5745         case dateTag:
5746         case numberTag:
5747           // Coerce booleans to `1` or `0` and dates to milliseconds.
5748           // Invalid dates are coerced to `NaN`.
5749           return eq(+object, +other);
5750
5751         case errorTag:
5752           return object.name == other.name && object.message == other.message;
5753
5754         case regexpTag:
5755         case stringTag:
5756           // Coerce regexes to strings and treat strings, primitives and objects,
5757           // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
5758           // for more details.
5759           return object == (other + '');
5760
5761         case mapTag:
5762           var convert = mapToArray;
5763
5764         case setTag:
5765           var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
5766           convert || (convert = setToArray);
5767
5768           if (object.size != other.size && !isPartial) {
5769             return false;
5770           }
5771           // Assume cyclic values are equal.
5772           var stacked = stack.get(object);
5773           if (stacked) {
5774             return stacked == other;
5775           }
5776           bitmask |= COMPARE_UNORDERED_FLAG;
5777
5778           // Recursively compare objects (susceptible to call stack limits).
5779           stack.set(object, other);
5780           var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
5781           stack['delete'](object);
5782           return result;
5783
5784         case symbolTag:
5785           if (symbolValueOf) {
5786             return symbolValueOf.call(object) == symbolValueOf.call(other);
5787           }
5788       }
5789       return false;
5790     }
5791
5792     /**
5793      * A specialized version of `baseIsEqualDeep` for objects with support for
5794      * partial deep comparisons.
5795      *
5796      * @private
5797      * @param {Object} object The object to compare.
5798      * @param {Object} other The other object to compare.
5799      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5800      * @param {Function} customizer The function to customize comparisons.
5801      * @param {Function} equalFunc The function to determine equivalents of values.
5802      * @param {Object} stack Tracks traversed `object` and `other` objects.
5803      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5804      */
5805     function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
5806       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5807           objProps = keys(object),
5808           objLength = objProps.length,
5809           othProps = keys(other),
5810           othLength = othProps.length;
5811
5812       if (objLength != othLength && !isPartial) {
5813         return false;
5814       }
5815       var index = objLength;
5816       while (index--) {
5817         var key = objProps[index];
5818         if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
5819           return false;
5820         }
5821       }
5822       // Assume cyclic values are equal.
5823       var stacked = stack.get(object);
5824       if (stacked && stack.get(other)) {
5825         return stacked == other;
5826       }
5827       var result = true;
5828       stack.set(object, other);
5829       stack.set(other, object);
5830
5831       var skipCtor = isPartial;
5832       while (++index < objLength) {
5833         key = objProps[index];
5834         var objValue = object[key],
5835             othValue = other[key];
5836
5837         if (customizer) {
5838           var compared = isPartial
5839             ? customizer(othValue, objValue, key, other, object, stack)
5840             : customizer(objValue, othValue, key, object, other, stack);
5841         }
5842         // Recursively compare objects (susceptible to call stack limits).
5843         if (!(compared === undefined
5844               ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
5845               : compared
5846             )) {
5847           result = false;
5848           break;
5849         }
5850         skipCtor || (skipCtor = key == 'constructor');
5851       }
5852       if (result && !skipCtor) {
5853         var objCtor = object.constructor,
5854             othCtor = other.constructor;
5855
5856         // Non `Object` object instances with different constructors are not equal.
5857         if (objCtor != othCtor &&
5858             ('constructor' in object && 'constructor' in other) &&
5859             !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
5860               typeof othCtor == 'function' && othCtor instanceof othCtor)) {
5861           result = false;
5862         }
5863       }
5864       stack['delete'](object);
5865       stack['delete'](other);
5866       return result;
5867     }
5868
5869     /**
5870      * A specialized version of `baseRest` which flattens the rest array.
5871      *
5872      * @private
5873      * @param {Function} func The function to apply a rest parameter to.
5874      * @returns {Function} Returns the new function.
5875      */
5876     function flatRest(func) {
5877       return setToString(overRest(func, undefined, flatten), func + '');
5878     }
5879
5880     /**
5881      * Creates an array of own enumerable property names and symbols of `object`.
5882      *
5883      * @private
5884      * @param {Object} object The object to query.
5885      * @returns {Array} Returns the array of property names and symbols.
5886      */
5887     function getAllKeys(object) {
5888       return baseGetAllKeys(object, keys, getSymbols);
5889     }
5890
5891     /**
5892      * Creates an array of own and inherited enumerable property names and
5893      * symbols of `object`.
5894      *
5895      * @private
5896      * @param {Object} object The object to query.
5897      * @returns {Array} Returns the array of property names and symbols.
5898      */
5899     function getAllKeysIn(object) {
5900       return baseGetAllKeys(object, keysIn, getSymbolsIn);
5901     }
5902
5903     /**
5904      * Gets metadata for `func`.
5905      *
5906      * @private
5907      * @param {Function} func The function to query.
5908      * @returns {*} Returns the metadata for `func`.
5909      */
5910     var getData = !metaMap ? noop : function(func) {
5911       return metaMap.get(func);
5912     };
5913
5914     /**
5915      * Gets the name of `func`.
5916      *
5917      * @private
5918      * @param {Function} func The function to query.
5919      * @returns {string} Returns the function name.
5920      */
5921     function getFuncName(func) {
5922       var result = (func.name + ''),
5923           array = realNames[result],
5924           length = hasOwnProperty.call(realNames, result) ? array.length : 0;
5925
5926       while (length--) {
5927         var data = array[length],
5928             otherFunc = data.func;
5929         if (otherFunc == null || otherFunc == func) {
5930           return data.name;
5931         }
5932       }
5933       return result;
5934     }
5935
5936     /**
5937      * Gets the argument placeholder value for `func`.
5938      *
5939      * @private
5940      * @param {Function} func The function to inspect.
5941      * @returns {*} Returns the placeholder value.
5942      */
5943     function getHolder(func) {
5944       var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
5945       return object.placeholder;
5946     }
5947
5948     /**
5949      * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
5950      * this function returns the custom method, otherwise it returns `baseIteratee`.
5951      * If arguments are provided, the chosen function is invoked with them and
5952      * its result is returned.
5953      *
5954      * @private
5955      * @param {*} [value] The value to convert to an iteratee.
5956      * @param {number} [arity] The arity of the created iteratee.
5957      * @returns {Function} Returns the chosen function or its result.
5958      */
5959     function getIteratee() {
5960       var result = lodash.iteratee || iteratee;
5961       result = result === iteratee ? baseIteratee : result;
5962       return arguments.length ? result(arguments[0], arguments[1]) : result;
5963     }
5964
5965     /**
5966      * Gets the data for `map`.
5967      *
5968      * @private
5969      * @param {Object} map The map to query.
5970      * @param {string} key The reference key.
5971      * @returns {*} Returns the map data.
5972      */
5973     function getMapData(map, key) {
5974       var data = map.__data__;
5975       return isKeyable(key)
5976         ? data[typeof key == 'string' ? 'string' : 'hash']
5977         : data.map;
5978     }
5979
5980     /**
5981      * Gets the property names, values, and compare flags of `object`.
5982      *
5983      * @private
5984      * @param {Object} object The object to query.
5985      * @returns {Array} Returns the match data of `object`.
5986      */
5987     function getMatchData(object) {
5988       var result = keys(object),
5989           length = result.length;
5990
5991       while (length--) {
5992         var key = result[length],
5993             value = object[key];
5994
5995         result[length] = [key, value, isStrictComparable(value)];
5996       }
5997       return result;
5998     }
5999
6000     /**
6001      * Gets the native function at `key` of `object`.
6002      *
6003      * @private
6004      * @param {Object} object The object to query.
6005      * @param {string} key The key of the method to get.
6006      * @returns {*} Returns the function if it's native, else `undefined`.
6007      */
6008     function getNative(object, key) {
6009       var value = getValue(object, key);
6010       return baseIsNative(value) ? value : undefined;
6011     }
6012
6013     /**
6014      * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
6015      *
6016      * @private
6017      * @param {*} value The value to query.
6018      * @returns {string} Returns the raw `toStringTag`.
6019      */
6020     function getRawTag(value) {
6021       var isOwn = hasOwnProperty.call(value, symToStringTag),
6022           tag = value[symToStringTag];
6023
6024       try {
6025         value[symToStringTag] = undefined;
6026         var unmasked = true;
6027       } catch (e) {}
6028
6029       var result = nativeObjectToString.call(value);
6030       if (unmasked) {
6031         if (isOwn) {
6032           value[symToStringTag] = tag;
6033         } else {
6034           delete value[symToStringTag];
6035         }
6036       }
6037       return result;
6038     }
6039
6040     /**
6041      * Creates an array of the own enumerable symbols of `object`.
6042      *
6043      * @private
6044      * @param {Object} object The object to query.
6045      * @returns {Array} Returns the array of symbols.
6046      */
6047     var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;
6048
6049     /**
6050      * Creates an array of the own and inherited enumerable symbols of `object`.
6051      *
6052      * @private
6053      * @param {Object} object The object to query.
6054      * @returns {Array} Returns the array of symbols.
6055      */
6056     var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
6057       var result = [];
6058       while (object) {
6059         arrayPush(result, getSymbols(object));
6060         object = getPrototype(object);
6061       }
6062       return result;
6063     };
6064
6065     /**
6066      * Gets the `toStringTag` of `value`.
6067      *
6068      * @private
6069      * @param {*} value The value to query.
6070      * @returns {string} Returns the `toStringTag`.
6071      */
6072     var getTag = baseGetTag;
6073
6074     // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
6075     if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
6076         (Map && getTag(new Map) != mapTag) ||
6077         (Promise && getTag(Promise.resolve()) != promiseTag) ||
6078         (Set && getTag(new Set) != setTag) ||
6079         (WeakMap && getTag(new WeakMap) != weakMapTag)) {
6080       getTag = function(value) {
6081         var result = baseGetTag(value),
6082             Ctor = result == objectTag ? value.constructor : undefined,
6083             ctorString = Ctor ? toSource(Ctor) : '';
6084
6085         if (ctorString) {
6086           switch (ctorString) {
6087             case dataViewCtorString: return dataViewTag;
6088             case mapCtorString: return mapTag;
6089             case promiseCtorString: return promiseTag;
6090             case setCtorString: return setTag;
6091             case weakMapCtorString: return weakMapTag;
6092           }
6093         }
6094         return result;
6095       };
6096     }
6097
6098     /**
6099      * Gets the view, applying any `transforms` to the `start` and `end` positions.
6100      *
6101      * @private
6102      * @param {number} start The start of the view.
6103      * @param {number} end The end of the view.
6104      * @param {Array} transforms The transformations to apply to the view.
6105      * @returns {Object} Returns an object containing the `start` and `end`
6106      *  positions of the view.
6107      */
6108     function getView(start, end, transforms) {
6109       var index = -1,
6110           length = transforms.length;
6111
6112       while (++index < length) {
6113         var data = transforms[index],
6114             size = data.size;
6115
6116         switch (data.type) {
6117           case 'drop':      start += size; break;
6118           case 'dropRight': end -= size; break;
6119           case 'take':      end = nativeMin(end, start + size); break;
6120           case 'takeRight': start = nativeMax(start, end - size); break;
6121         }
6122       }
6123       return { 'start': start, 'end': end };
6124     }
6125
6126     /**
6127      * Extracts wrapper details from the `source` body comment.
6128      *
6129      * @private
6130      * @param {string} source The source to inspect.
6131      * @returns {Array} Returns the wrapper details.
6132      */
6133     function getWrapDetails(source) {
6134       var match = source.match(reWrapDetails);
6135       return match ? match[1].split(reSplitDetails) : [];
6136     }
6137
6138     /**
6139      * Checks if `path` exists on `object`.
6140      *
6141      * @private
6142      * @param {Object} object The object to query.
6143      * @param {Array|string} path The path to check.
6144      * @param {Function} hasFunc The function to check properties.
6145      * @returns {boolean} Returns `true` if `path` exists, else `false`.
6146      */
6147     function hasPath(object, path, hasFunc) {
6148       path = castPath(path, object);
6149
6150       var index = -1,
6151           length = path.length,
6152           result = false;
6153
6154       while (++index < length) {
6155         var key = toKey(path[index]);
6156         if (!(result = object != null && hasFunc(object, key))) {
6157           break;
6158         }
6159         object = object[key];
6160       }
6161       if (result || ++index != length) {
6162         return result;
6163       }
6164       length = object == null ? 0 : object.length;
6165       return !!length && isLength(length) && isIndex(key, length) &&
6166         (isArray(object) || isArguments(object));
6167     }
6168
6169     /**
6170      * Initializes an array clone.
6171      *
6172      * @private
6173      * @param {Array} array The array to clone.
6174      * @returns {Array} Returns the initialized clone.
6175      */
6176     function initCloneArray(array) {
6177       var length = array.length,
6178           result = array.constructor(length);
6179
6180       // Add properties assigned by `RegExp#exec`.
6181       if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
6182         result.index = array.index;
6183         result.input = array.input;
6184       }
6185       return result;
6186     }
6187
6188     /**
6189      * Initializes an object clone.
6190      *
6191      * @private
6192      * @param {Object} object The object to clone.
6193      * @returns {Object} Returns the initialized clone.
6194      */
6195     function initCloneObject(object) {
6196       return (typeof object.constructor == 'function' && !isPrototype(object))
6197         ? baseCreate(getPrototype(object))
6198         : {};
6199     }
6200
6201     /**
6202      * Initializes an object clone based on its `toStringTag`.
6203      *
6204      * **Note:** This function only supports cloning values with tags of
6205      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
6206      *
6207      * @private
6208      * @param {Object} object The object to clone.
6209      * @param {string} tag The `toStringTag` of the object to clone.
6210      * @param {Function} cloneFunc The function to clone values.
6211      * @param {boolean} [isDeep] Specify a deep clone.
6212      * @returns {Object} Returns the initialized clone.
6213      */
6214     function initCloneByTag(object, tag, cloneFunc, isDeep) {
6215       var Ctor = object.constructor;
6216       switch (tag) {
6217         case arrayBufferTag:
6218           return cloneArrayBuffer(object);
6219
6220         case boolTag:
6221         case dateTag:
6222           return new Ctor(+object);
6223
6224         case dataViewTag:
6225           return cloneDataView(object, isDeep);
6226
6227         case float32Tag: case float64Tag:
6228         case int8Tag: case int16Tag: case int32Tag:
6229         case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
6230           return cloneTypedArray(object, isDeep);
6231
6232         case mapTag:
6233           return cloneMap(object, isDeep, cloneFunc);
6234
6235         case numberTag:
6236         case stringTag:
6237           return new Ctor(object);
6238
6239         case regexpTag:
6240           return cloneRegExp(object);
6241
6242         case setTag:
6243           return cloneSet(object, isDeep, cloneFunc);
6244
6245         case symbolTag:
6246           return cloneSymbol(object);
6247       }
6248     }
6249
6250     /**
6251      * Inserts wrapper `details` in a comment at the top of the `source` body.
6252      *
6253      * @private
6254      * @param {string} source The source to modify.
6255      * @returns {Array} details The details to insert.
6256      * @returns {string} Returns the modified source.
6257      */
6258     function insertWrapDetails(source, details) {
6259       var length = details.length;
6260       if (!length) {
6261         return source;
6262       }
6263       var lastIndex = length - 1;
6264       details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
6265       details = details.join(length > 2 ? ', ' : ' ');
6266       return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
6267     }
6268
6269     /**
6270      * Checks if `value` is a flattenable `arguments` object or array.
6271      *
6272      * @private
6273      * @param {*} value The value to check.
6274      * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
6275      */
6276     function isFlattenable(value) {
6277       return isArray(value) || isArguments(value) ||
6278         !!(spreadableSymbol && value && value[spreadableSymbol]);
6279     }
6280
6281     /**
6282      * Checks if `value` is a valid array-like index.
6283      *
6284      * @private
6285      * @param {*} value The value to check.
6286      * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
6287      * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
6288      */
6289     function isIndex(value, length) {
6290       length = length == null ? MAX_SAFE_INTEGER : length;
6291       return !!length &&
6292         (typeof value == 'number' || reIsUint.test(value)) &&
6293         (value > -1 && value % 1 == 0 && value < length);
6294     }
6295
6296     /**
6297      * Checks if the given arguments are from an iteratee call.
6298      *
6299      * @private
6300      * @param {*} value The potential iteratee value argument.
6301      * @param {*} index The potential iteratee index or key argument.
6302      * @param {*} object The potential iteratee object argument.
6303      * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
6304      *  else `false`.
6305      */
6306     function isIterateeCall(value, index, object) {
6307       if (!isObject(object)) {
6308         return false;
6309       }
6310       var type = typeof index;
6311       if (type == 'number'
6312             ? (isArrayLike(object) && isIndex(index, object.length))
6313             : (type == 'string' && index in object)
6314           ) {
6315         return eq(object[index], value);
6316       }
6317       return false;
6318     }
6319
6320     /**
6321      * Checks if `value` is a property name and not a property path.
6322      *
6323      * @private
6324      * @param {*} value The value to check.
6325      * @param {Object} [object] The object to query keys on.
6326      * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
6327      */
6328     function isKey(value, object) {
6329       if (isArray(value)) {
6330         return false;
6331       }
6332       var type = typeof value;
6333       if (type == 'number' || type == 'symbol' || type == 'boolean' ||
6334           value == null || isSymbol(value)) {
6335         return true;
6336       }
6337       return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
6338         (object != null && value in Object(object));
6339     }
6340
6341     /**
6342      * Checks if `value` is suitable for use as unique object key.
6343      *
6344      * @private
6345      * @param {*} value The value to check.
6346      * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
6347      */
6348     function isKeyable(value) {
6349       var type = typeof value;
6350       return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
6351         ? (value !== '__proto__')
6352         : (value === null);
6353     }
6354
6355     /**
6356      * Checks if `func` has a lazy counterpart.
6357      *
6358      * @private
6359      * @param {Function} func The function to check.
6360      * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
6361      *  else `false`.
6362      */
6363     function isLaziable(func) {
6364       var funcName = getFuncName(func),
6365           other = lodash[funcName];
6366
6367       if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
6368         return false;
6369       }
6370       if (func === other) {
6371         return true;
6372       }
6373       var data = getData(other);
6374       return !!data && func === data[0];
6375     }
6376
6377     /**
6378      * Checks if `func` has its source masked.
6379      *
6380      * @private
6381      * @param {Function} func The function to check.
6382      * @returns {boolean} Returns `true` if `func` is masked, else `false`.
6383      */
6384     function isMasked(func) {
6385       return !!maskSrcKey && (maskSrcKey in func);
6386     }
6387
6388     /**
6389      * Checks if `func` is capable of being masked.
6390      *
6391      * @private
6392      * @param {*} value The value to check.
6393      * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
6394      */
6395     var isMaskable = coreJsData ? isFunction : stubFalse;
6396
6397     /**
6398      * Checks if `value` is likely a prototype object.
6399      *
6400      * @private
6401      * @param {*} value The value to check.
6402      * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
6403      */
6404     function isPrototype(value) {
6405       var Ctor = value && value.constructor,
6406           proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
6407
6408       return value === proto;
6409     }
6410
6411     /**
6412      * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
6413      *
6414      * @private
6415      * @param {*} value The value to check.
6416      * @returns {boolean} Returns `true` if `value` if suitable for strict
6417      *  equality comparisons, else `false`.
6418      */
6419     function isStrictComparable(value) {
6420       return value === value && !isObject(value);
6421     }
6422
6423     /**
6424      * A specialized version of `matchesProperty` for source values suitable
6425      * for strict equality comparisons, i.e. `===`.
6426      *
6427      * @private
6428      * @param {string} key The key of the property to get.
6429      * @param {*} srcValue The value to match.
6430      * @returns {Function} Returns the new spec function.
6431      */
6432     function matchesStrictComparable(key, srcValue) {
6433       return function(object) {
6434         if (object == null) {
6435           return false;
6436         }
6437         return object[key] === srcValue &&
6438           (srcValue !== undefined || (key in Object(object)));
6439       };
6440     }
6441
6442     /**
6443      * A specialized version of `_.memoize` which clears the memoized function's
6444      * cache when it exceeds `MAX_MEMOIZE_SIZE`.
6445      *
6446      * @private
6447      * @param {Function} func The function to have its output memoized.
6448      * @returns {Function} Returns the new memoized function.
6449      */
6450     function memoizeCapped(func) {
6451       var result = memoize(func, function(key) {
6452         if (cache.size === MAX_MEMOIZE_SIZE) {
6453           cache.clear();
6454         }
6455         return key;
6456       });
6457
6458       var cache = result.cache;
6459       return result;
6460     }
6461
6462     /**
6463      * Merges the function metadata of `source` into `data`.
6464      *
6465      * Merging metadata reduces the number of wrappers used to invoke a function.
6466      * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
6467      * may be applied regardless of execution order. Methods like `_.ary` and
6468      * `_.rearg` modify function arguments, making the order in which they are
6469      * executed important, preventing the merging of metadata. However, we make
6470      * an exception for a safe combined case where curried functions have `_.ary`
6471      * and or `_.rearg` applied.
6472      *
6473      * @private
6474      * @param {Array} data The destination metadata.
6475      * @param {Array} source The source metadata.
6476      * @returns {Array} Returns `data`.
6477      */
6478     function mergeData(data, source) {
6479       var bitmask = data[1],
6480           srcBitmask = source[1],
6481           newBitmask = bitmask | srcBitmask,
6482           isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
6483
6484       var isCombo =
6485         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
6486         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
6487         ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
6488
6489       // Exit early if metadata can't be merged.
6490       if (!(isCommon || isCombo)) {
6491         return data;
6492       }
6493       // Use source `thisArg` if available.
6494       if (srcBitmask & WRAP_BIND_FLAG) {
6495         data[2] = source[2];
6496         // Set when currying a bound function.
6497         newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
6498       }
6499       // Compose partial arguments.
6500       var value = source[3];
6501       if (value) {
6502         var partials = data[3];
6503         data[3] = partials ? composeArgs(partials, value, source[4]) : value;
6504         data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
6505       }
6506       // Compose partial right arguments.
6507       value = source[5];
6508       if (value) {
6509         partials = data[5];
6510         data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
6511         data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
6512       }
6513       // Use source `argPos` if available.
6514       value = source[7];
6515       if (value) {
6516         data[7] = value;
6517       }
6518       // Use source `ary` if it's smaller.
6519       if (srcBitmask & WRAP_ARY_FLAG) {
6520         data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
6521       }
6522       // Use source `arity` if one is not provided.
6523       if (data[9] == null) {
6524         data[9] = source[9];
6525       }
6526       // Use source `func` and merge bitmasks.
6527       data[0] = source[0];
6528       data[1] = newBitmask;
6529
6530       return data;
6531     }
6532
6533     /**
6534      * Used by `_.defaultsDeep` to customize its `_.merge` use.
6535      *
6536      * @private
6537      * @param {*} objValue The destination value.
6538      * @param {*} srcValue The source value.
6539      * @param {string} key The key of the property to merge.
6540      * @param {Object} object The parent object of `objValue`.
6541      * @param {Object} source The parent object of `srcValue`.
6542      * @param {Object} [stack] Tracks traversed source values and their merged
6543      *  counterparts.
6544      * @returns {*} Returns the value to assign.
6545      */
6546     function mergeDefaults(objValue, srcValue, key, object, source, stack) {
6547       if (isObject(objValue) && isObject(srcValue)) {
6548         // Recursively merge objects and arrays (susceptible to call stack limits).
6549         stack.set(srcValue, objValue);
6550         baseMerge(objValue, srcValue, undefined, mergeDefaults, stack);
6551         stack['delete'](srcValue);
6552       }
6553       return objValue;
6554     }
6555
6556     /**
6557      * This function is like
6558      * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
6559      * except that it includes inherited enumerable properties.
6560      *
6561      * @private
6562      * @param {Object} object The object to query.
6563      * @returns {Array} Returns the array of property names.
6564      */
6565     function nativeKeysIn(object) {
6566       var result = [];
6567       if (object != null) {
6568         for (var key in Object(object)) {
6569           result.push(key);
6570         }
6571       }
6572       return result;
6573     }
6574
6575     /**
6576      * Converts `value` to a string using `Object.prototype.toString`.
6577      *
6578      * @private
6579      * @param {*} value The value to convert.
6580      * @returns {string} Returns the converted string.
6581      */
6582     function objectToString(value) {
6583       return nativeObjectToString.call(value);
6584     }
6585
6586     /**
6587      * A specialized version of `baseRest` which transforms the rest array.
6588      *
6589      * @private
6590      * @param {Function} func The function to apply a rest parameter to.
6591      * @param {number} [start=func.length-1] The start position of the rest parameter.
6592      * @param {Function} transform The rest array transform.
6593      * @returns {Function} Returns the new function.
6594      */
6595     function overRest(func, start, transform) {
6596       start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
6597       return function() {
6598         var args = arguments,
6599             index = -1,
6600             length = nativeMax(args.length - start, 0),
6601             array = Array(length);
6602
6603         while (++index < length) {
6604           array[index] = args[start + index];
6605         }
6606         index = -1;
6607         var otherArgs = Array(start + 1);
6608         while (++index < start) {
6609           otherArgs[index] = args[index];
6610         }
6611         otherArgs[start] = transform(array);
6612         return apply(func, this, otherArgs);
6613       };
6614     }
6615
6616     /**
6617      * Gets the parent value at `path` of `object`.
6618      *
6619      * @private
6620      * @param {Object} object The object to query.
6621      * @param {Array} path The path to get the parent value of.
6622      * @returns {*} Returns the parent value.
6623      */
6624     function parent(object, path) {
6625       return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
6626     }
6627
6628     /**
6629      * Reorder `array` according to the specified indexes where the element at
6630      * the first index is assigned as the first element, the element at
6631      * the second index is assigned as the second element, and so on.
6632      *
6633      * @private
6634      * @param {Array} array The array to reorder.
6635      * @param {Array} indexes The arranged array indexes.
6636      * @returns {Array} Returns `array`.
6637      */
6638     function reorder(array, indexes) {
6639       var arrLength = array.length,
6640           length = nativeMin(indexes.length, arrLength),
6641           oldArray = copyArray(array);
6642
6643       while (length--) {
6644         var index = indexes[length];
6645         array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
6646       }
6647       return array;
6648     }
6649
6650     /**
6651      * Sets metadata for `func`.
6652      *
6653      * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
6654      * period of time, it will trip its breaker and transition to an identity
6655      * function to avoid garbage collection pauses in V8. See
6656      * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
6657      * for more details.
6658      *
6659      * @private
6660      * @param {Function} func The function to associate metadata with.
6661      * @param {*} data The metadata.
6662      * @returns {Function} Returns `func`.
6663      */
6664     var setData = shortOut(baseSetData);
6665
6666     /**
6667      * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
6668      *
6669      * @private
6670      * @param {Function} func The function to delay.
6671      * @param {number} wait The number of milliseconds to delay invocation.
6672      * @returns {number|Object} Returns the timer id or timeout object.
6673      */
6674     var setTimeout = ctxSetTimeout || function(func, wait) {
6675       return root.setTimeout(func, wait);
6676     };
6677
6678     /**
6679      * Sets the `toString` method of `func` to return `string`.
6680      *
6681      * @private
6682      * @param {Function} func The function to modify.
6683      * @param {Function} string The `toString` result.
6684      * @returns {Function} Returns `func`.
6685      */
6686     var setToString = shortOut(baseSetToString);
6687
6688     /**
6689      * Sets the `toString` method of `wrapper` to mimic the source of `reference`
6690      * with wrapper details in a comment at the top of the source body.
6691      *
6692      * @private
6693      * @param {Function} wrapper The function to modify.
6694      * @param {Function} reference The reference function.
6695      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6696      * @returns {Function} Returns `wrapper`.
6697      */
6698     function setWrapToString(wrapper, reference, bitmask) {
6699       var source = (reference + '');
6700       return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
6701     }
6702
6703     /**
6704      * Creates a function that'll short out and invoke `identity` instead
6705      * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
6706      * milliseconds.
6707      *
6708      * @private
6709      * @param {Function} func The function to restrict.
6710      * @returns {Function} Returns the new shortable function.
6711      */
6712     function shortOut(func) {
6713       var count = 0,
6714           lastCalled = 0;
6715
6716       return function() {
6717         var stamp = nativeNow(),
6718             remaining = HOT_SPAN - (stamp - lastCalled);
6719
6720         lastCalled = stamp;
6721         if (remaining > 0) {
6722           if (++count >= HOT_COUNT) {
6723             return arguments[0];
6724           }
6725         } else {
6726           count = 0;
6727         }
6728         return func.apply(undefined, arguments);
6729       };
6730     }
6731
6732     /**
6733      * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
6734      *
6735      * @private
6736      * @param {Array} array The array to shuffle.
6737      * @param {number} [size=array.length] The size of `array`.
6738      * @returns {Array} Returns `array`.
6739      */
6740     function shuffleSelf(array, size) {
6741       var index = -1,
6742           length = array.length,
6743           lastIndex = length - 1;
6744
6745       size = size === undefined ? length : size;
6746       while (++index < size) {
6747         var rand = baseRandom(index, lastIndex),
6748             value = array[rand];
6749
6750         array[rand] = array[index];
6751         array[index] = value;
6752       }
6753       array.length = size;
6754       return array;
6755     }
6756
6757     /**
6758      * Converts `string` to a property path array.
6759      *
6760      * @private
6761      * @param {string} string The string to convert.
6762      * @returns {Array} Returns the property path array.
6763      */
6764     var stringToPath = memoizeCapped(function(string) {
6765       var result = [];
6766       if (reLeadingDot.test(string)) {
6767         result.push('');
6768       }
6769       string.replace(rePropName, function(match, number, quote, string) {
6770         result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
6771       });
6772       return result;
6773     });
6774
6775     /**
6776      * Converts `value` to a string key if it's not a string or symbol.
6777      *
6778      * @private
6779      * @param {*} value The value to inspect.
6780      * @returns {string|symbol} Returns the key.
6781      */
6782     function toKey(value) {
6783       if (typeof value == 'string' || isSymbol(value)) {
6784         return value;
6785       }
6786       var result = (value + '');
6787       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
6788     }
6789
6790     /**
6791      * Converts `func` to its source code.
6792      *
6793      * @private
6794      * @param {Function} func The function to convert.
6795      * @returns {string} Returns the source code.
6796      */
6797     function toSource(func) {
6798       if (func != null) {
6799         try {
6800           return funcToString.call(func);
6801         } catch (e) {}
6802         try {
6803           return (func + '');
6804         } catch (e) {}
6805       }
6806       return '';
6807     }
6808
6809     /**
6810      * Updates wrapper `details` based on `bitmask` flags.
6811      *
6812      * @private
6813      * @returns {Array} details The details to modify.
6814      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6815      * @returns {Array} Returns `details`.
6816      */
6817     function updateWrapDetails(details, bitmask) {
6818       arrayEach(wrapFlags, function(pair) {
6819         var value = '_.' + pair[0];
6820         if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
6821           details.push(value);
6822         }
6823       });
6824       return details.sort();
6825     }
6826
6827     /**
6828      * Creates a clone of `wrapper`.
6829      *
6830      * @private
6831      * @param {Object} wrapper The wrapper to clone.
6832      * @returns {Object} Returns the cloned wrapper.
6833      */
6834     function wrapperClone(wrapper) {
6835       if (wrapper instanceof LazyWrapper) {
6836         return wrapper.clone();
6837       }
6838       var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
6839       result.__actions__ = copyArray(wrapper.__actions__);
6840       result.__index__  = wrapper.__index__;
6841       result.__values__ = wrapper.__values__;
6842       return result;
6843     }
6844
6845     /*------------------------------------------------------------------------*/
6846
6847     /**
6848      * Creates an array of elements split into groups the length of `size`.
6849      * If `array` can't be split evenly, the final chunk will be the remaining
6850      * elements.
6851      *
6852      * @static
6853      * @memberOf _
6854      * @since 3.0.0
6855      * @category Array
6856      * @param {Array} array The array to process.
6857      * @param {number} [size=1] The length of each chunk
6858      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
6859      * @returns {Array} Returns the new array of chunks.
6860      * @example
6861      *
6862      * _.chunk(['a', 'b', 'c', 'd'], 2);
6863      * // => [['a', 'b'], ['c', 'd']]
6864      *
6865      * _.chunk(['a', 'b', 'c', 'd'], 3);
6866      * // => [['a', 'b', 'c'], ['d']]
6867      */
6868     function chunk(array, size, guard) {
6869       if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
6870         size = 1;
6871       } else {
6872         size = nativeMax(toInteger(size), 0);
6873       }
6874       var length = array == null ? 0 : array.length;
6875       if (!length || size < 1) {
6876         return [];
6877       }
6878       var index = 0,
6879           resIndex = 0,
6880           result = Array(nativeCeil(length / size));
6881
6882       while (index < length) {
6883         result[resIndex++] = baseSlice(array, index, (index += size));
6884       }
6885       return result;
6886     }
6887
6888     /**
6889      * Creates an array with all falsey values removed. The values `false`, `null`,
6890      * `0`, `""`, `undefined`, and `NaN` are falsey.
6891      *
6892      * @static
6893      * @memberOf _
6894      * @since 0.1.0
6895      * @category Array
6896      * @param {Array} array The array to compact.
6897      * @returns {Array} Returns the new array of filtered values.
6898      * @example
6899      *
6900      * _.compact([0, 1, false, 2, '', 3]);
6901      * // => [1, 2, 3]
6902      */
6903     function compact(array) {
6904       var index = -1,
6905           length = array == null ? 0 : array.length,
6906           resIndex = 0,
6907           result = [];
6908
6909       while (++index < length) {
6910         var value = array[index];
6911         if (value) {
6912           result[resIndex++] = value;
6913         }
6914       }
6915       return result;
6916     }
6917
6918     /**
6919      * Creates a new array concatenating `array` with any additional arrays
6920      * and/or values.
6921      *
6922      * @static
6923      * @memberOf _
6924      * @since 4.0.0
6925      * @category Array
6926      * @param {Array} array The array to concatenate.
6927      * @param {...*} [values] The values to concatenate.
6928      * @returns {Array} Returns the new concatenated array.
6929      * @example
6930      *
6931      * var array = [1];
6932      * var other = _.concat(array, 2, [3], [[4]]);
6933      *
6934      * console.log(other);
6935      * // => [1, 2, 3, [4]]
6936      *
6937      * console.log(array);
6938      * // => [1]
6939      */
6940     function concat() {
6941       var length = arguments.length;
6942       if (!length) {
6943         return [];
6944       }
6945       var args = Array(length - 1),
6946           array = arguments[0],
6947           index = length;
6948
6949       while (index--) {
6950         args[index - 1] = arguments[index];
6951       }
6952       return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
6953     }
6954
6955     /**
6956      * Creates an array of `array` values not included in the other given arrays
6957      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
6958      * for equality comparisons. The order and references of result values are
6959      * determined by the first array.
6960      *
6961      * **Note:** Unlike `_.pullAll`, this method returns a new array.
6962      *
6963      * @static
6964      * @memberOf _
6965      * @since 0.1.0
6966      * @category Array
6967      * @param {Array} array The array to inspect.
6968      * @param {...Array} [values] The values to exclude.
6969      * @returns {Array} Returns the new array of filtered values.
6970      * @see _.without, _.xor
6971      * @example
6972      *
6973      * _.difference([2, 1], [2, 3]);
6974      * // => [1]
6975      */
6976     var difference = baseRest(function(array, values) {
6977       return isArrayLikeObject(array)
6978         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
6979         : [];
6980     });
6981
6982     /**
6983      * This method is like `_.difference` except that it accepts `iteratee` which
6984      * is invoked for each element of `array` and `values` to generate the criterion
6985      * by which they're compared. The order and references of result values are
6986      * determined by the first array. The iteratee is invoked with one argument:
6987      * (value).
6988      *
6989      * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
6990      *
6991      * @static
6992      * @memberOf _
6993      * @since 4.0.0
6994      * @category Array
6995      * @param {Array} array The array to inspect.
6996      * @param {...Array} [values] The values to exclude.
6997      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
6998      * @returns {Array} Returns the new array of filtered values.
6999      * @example
7000      *
7001      * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7002      * // => [1.2]
7003      *
7004      * // The `_.property` iteratee shorthand.
7005      * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
7006      * // => [{ 'x': 2 }]
7007      */
7008     var differenceBy = baseRest(function(array, values) {
7009       var iteratee = last(values);
7010       if (isArrayLikeObject(iteratee)) {
7011         iteratee = undefined;
7012       }
7013       return isArrayLikeObject(array)
7014         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
7015         : [];
7016     });
7017
7018     /**
7019      * This method is like `_.difference` except that it accepts `comparator`
7020      * which is invoked to compare elements of `array` to `values`. The order and
7021      * references of result values are determined by the first array. The comparator
7022      * is invoked with two arguments: (arrVal, othVal).
7023      *
7024      * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
7025      *
7026      * @static
7027      * @memberOf _
7028      * @since 4.0.0
7029      * @category Array
7030      * @param {Array} array The array to inspect.
7031      * @param {...Array} [values] The values to exclude.
7032      * @param {Function} [comparator] The comparator invoked per element.
7033      * @returns {Array} Returns the new array of filtered values.
7034      * @example
7035      *
7036      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7037      *
7038      * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
7039      * // => [{ 'x': 2, 'y': 1 }]
7040      */
7041     var differenceWith = baseRest(function(array, values) {
7042       var comparator = last(values);
7043       if (isArrayLikeObject(comparator)) {
7044         comparator = undefined;
7045       }
7046       return isArrayLikeObject(array)
7047         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
7048         : [];
7049     });
7050
7051     /**
7052      * Creates a slice of `array` with `n` elements dropped from the beginning.
7053      *
7054      * @static
7055      * @memberOf _
7056      * @since 0.5.0
7057      * @category Array
7058      * @param {Array} array The array to query.
7059      * @param {number} [n=1] The number of elements to drop.
7060      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7061      * @returns {Array} Returns the slice of `array`.
7062      * @example
7063      *
7064      * _.drop([1, 2, 3]);
7065      * // => [2, 3]
7066      *
7067      * _.drop([1, 2, 3], 2);
7068      * // => [3]
7069      *
7070      * _.drop([1, 2, 3], 5);
7071      * // => []
7072      *
7073      * _.drop([1, 2, 3], 0);
7074      * // => [1, 2, 3]
7075      */
7076     function drop(array, n, guard) {
7077       var length = array == null ? 0 : array.length;
7078       if (!length) {
7079         return [];
7080       }
7081       n = (guard || n === undefined) ? 1 : toInteger(n);
7082       return baseSlice(array, n < 0 ? 0 : n, length);
7083     }
7084
7085     /**
7086      * Creates a slice of `array` with `n` elements dropped from the end.
7087      *
7088      * @static
7089      * @memberOf _
7090      * @since 3.0.0
7091      * @category Array
7092      * @param {Array} array The array to query.
7093      * @param {number} [n=1] The number of elements to drop.
7094      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7095      * @returns {Array} Returns the slice of `array`.
7096      * @example
7097      *
7098      * _.dropRight([1, 2, 3]);
7099      * // => [1, 2]
7100      *
7101      * _.dropRight([1, 2, 3], 2);
7102      * // => [1]
7103      *
7104      * _.dropRight([1, 2, 3], 5);
7105      * // => []
7106      *
7107      * _.dropRight([1, 2, 3], 0);
7108      * // => [1, 2, 3]
7109      */
7110     function dropRight(array, n, guard) {
7111       var length = array == null ? 0 : array.length;
7112       if (!length) {
7113         return [];
7114       }
7115       n = (guard || n === undefined) ? 1 : toInteger(n);
7116       n = length - n;
7117       return baseSlice(array, 0, n < 0 ? 0 : n);
7118     }
7119
7120     /**
7121      * Creates a slice of `array` excluding elements dropped from the end.
7122      * Elements are dropped until `predicate` returns falsey. The predicate is
7123      * invoked with three arguments: (value, index, array).
7124      *
7125      * @static
7126      * @memberOf _
7127      * @since 3.0.0
7128      * @category Array
7129      * @param {Array} array The array to query.
7130      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7131      * @returns {Array} Returns the slice of `array`.
7132      * @example
7133      *
7134      * var users = [
7135      *   { 'user': 'barney',  'active': true },
7136      *   { 'user': 'fred',    'active': false },
7137      *   { 'user': 'pebbles', 'active': false }
7138      * ];
7139      *
7140      * _.dropRightWhile(users, function(o) { return !o.active; });
7141      * // => objects for ['barney']
7142      *
7143      * // The `_.matches` iteratee shorthand.
7144      * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
7145      * // => objects for ['barney', 'fred']
7146      *
7147      * // The `_.matchesProperty` iteratee shorthand.
7148      * _.dropRightWhile(users, ['active', false]);
7149      * // => objects for ['barney']
7150      *
7151      * // The `_.property` iteratee shorthand.
7152      * _.dropRightWhile(users, 'active');
7153      * // => objects for ['barney', 'fred', 'pebbles']
7154      */
7155     function dropRightWhile(array, predicate) {
7156       return (array && array.length)
7157         ? baseWhile(array, getIteratee(predicate, 3), true, true)
7158         : [];
7159     }
7160
7161     /**
7162      * Creates a slice of `array` excluding elements dropped from the beginning.
7163      * Elements are dropped until `predicate` returns falsey. The predicate is
7164      * invoked with three arguments: (value, index, array).
7165      *
7166      * @static
7167      * @memberOf _
7168      * @since 3.0.0
7169      * @category Array
7170      * @param {Array} array The array to query.
7171      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7172      * @returns {Array} Returns the slice of `array`.
7173      * @example
7174      *
7175      * var users = [
7176      *   { 'user': 'barney',  'active': false },
7177      *   { 'user': 'fred',    'active': false },
7178      *   { 'user': 'pebbles', 'active': true }
7179      * ];
7180      *
7181      * _.dropWhile(users, function(o) { return !o.active; });
7182      * // => objects for ['pebbles']
7183      *
7184      * // The `_.matches` iteratee shorthand.
7185      * _.dropWhile(users, { 'user': 'barney', 'active': false });
7186      * // => objects for ['fred', 'pebbles']
7187      *
7188      * // The `_.matchesProperty` iteratee shorthand.
7189      * _.dropWhile(users, ['active', false]);
7190      * // => objects for ['pebbles']
7191      *
7192      * // The `_.property` iteratee shorthand.
7193      * _.dropWhile(users, 'active');
7194      * // => objects for ['barney', 'fred', 'pebbles']
7195      */
7196     function dropWhile(array, predicate) {
7197       return (array && array.length)
7198         ? baseWhile(array, getIteratee(predicate, 3), true)
7199         : [];
7200     }
7201
7202     /**
7203      * Fills elements of `array` with `value` from `start` up to, but not
7204      * including, `end`.
7205      *
7206      * **Note:** This method mutates `array`.
7207      *
7208      * @static
7209      * @memberOf _
7210      * @since 3.2.0
7211      * @category Array
7212      * @param {Array} array The array to fill.
7213      * @param {*} value The value to fill `array` with.
7214      * @param {number} [start=0] The start position.
7215      * @param {number} [end=array.length] The end position.
7216      * @returns {Array} Returns `array`.
7217      * @example
7218      *
7219      * var array = [1, 2, 3];
7220      *
7221      * _.fill(array, 'a');
7222      * console.log(array);
7223      * // => ['a', 'a', 'a']
7224      *
7225      * _.fill(Array(3), 2);
7226      * // => [2, 2, 2]
7227      *
7228      * _.fill([4, 6, 8, 10], '*', 1, 3);
7229      * // => [4, '*', '*', 10]
7230      */
7231     function fill(array, value, start, end) {
7232       var length = array == null ? 0 : array.length;
7233       if (!length) {
7234         return [];
7235       }
7236       if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
7237         start = 0;
7238         end = length;
7239       }
7240       return baseFill(array, value, start, end);
7241     }
7242
7243     /**
7244      * This method is like `_.find` except that it returns the index of the first
7245      * element `predicate` returns truthy for instead of the element itself.
7246      *
7247      * @static
7248      * @memberOf _
7249      * @since 1.1.0
7250      * @category Array
7251      * @param {Array} array The array to inspect.
7252      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7253      * @param {number} [fromIndex=0] The index to search from.
7254      * @returns {number} Returns the index of the found element, else `-1`.
7255      * @example
7256      *
7257      * var users = [
7258      *   { 'user': 'barney',  'active': false },
7259      *   { 'user': 'fred',    'active': false },
7260      *   { 'user': 'pebbles', 'active': true }
7261      * ];
7262      *
7263      * _.findIndex(users, function(o) { return o.user == 'barney'; });
7264      * // => 0
7265      *
7266      * // The `_.matches` iteratee shorthand.
7267      * _.findIndex(users, { 'user': 'fred', 'active': false });
7268      * // => 1
7269      *
7270      * // The `_.matchesProperty` iteratee shorthand.
7271      * _.findIndex(users, ['active', false]);
7272      * // => 0
7273      *
7274      * // The `_.property` iteratee shorthand.
7275      * _.findIndex(users, 'active');
7276      * // => 2
7277      */
7278     function findIndex(array, predicate, fromIndex) {
7279       var length = array == null ? 0 : array.length;
7280       if (!length) {
7281         return -1;
7282       }
7283       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7284       if (index < 0) {
7285         index = nativeMax(length + index, 0);
7286       }
7287       return baseFindIndex(array, getIteratee(predicate, 3), index);
7288     }
7289
7290     /**
7291      * This method is like `_.findIndex` except that it iterates over elements
7292      * of `collection` from right to left.
7293      *
7294      * @static
7295      * @memberOf _
7296      * @since 2.0.0
7297      * @category Array
7298      * @param {Array} array The array to inspect.
7299      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7300      * @param {number} [fromIndex=array.length-1] The index to search from.
7301      * @returns {number} Returns the index of the found element, else `-1`.
7302      * @example
7303      *
7304      * var users = [
7305      *   { 'user': 'barney',  'active': true },
7306      *   { 'user': 'fred',    'active': false },
7307      *   { 'user': 'pebbles', 'active': false }
7308      * ];
7309      *
7310      * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
7311      * // => 2
7312      *
7313      * // The `_.matches` iteratee shorthand.
7314      * _.findLastIndex(users, { 'user': 'barney', 'active': true });
7315      * // => 0
7316      *
7317      * // The `_.matchesProperty` iteratee shorthand.
7318      * _.findLastIndex(users, ['active', false]);
7319      * // => 2
7320      *
7321      * // The `_.property` iteratee shorthand.
7322      * _.findLastIndex(users, 'active');
7323      * // => 0
7324      */
7325     function findLastIndex(array, predicate, fromIndex) {
7326       var length = array == null ? 0 : array.length;
7327       if (!length) {
7328         return -1;
7329       }
7330       var index = length - 1;
7331       if (fromIndex !== undefined) {
7332         index = toInteger(fromIndex);
7333         index = fromIndex < 0
7334           ? nativeMax(length + index, 0)
7335           : nativeMin(index, length - 1);
7336       }
7337       return baseFindIndex(array, getIteratee(predicate, 3), index, true);
7338     }
7339
7340     /**
7341      * Flattens `array` a single level deep.
7342      *
7343      * @static
7344      * @memberOf _
7345      * @since 0.1.0
7346      * @category Array
7347      * @param {Array} array The array to flatten.
7348      * @returns {Array} Returns the new flattened array.
7349      * @example
7350      *
7351      * _.flatten([1, [2, [3, [4]], 5]]);
7352      * // => [1, 2, [3, [4]], 5]
7353      */
7354     function flatten(array) {
7355       var length = array == null ? 0 : array.length;
7356       return length ? baseFlatten(array, 1) : [];
7357     }
7358
7359     /**
7360      * Recursively flattens `array`.
7361      *
7362      * @static
7363      * @memberOf _
7364      * @since 3.0.0
7365      * @category Array
7366      * @param {Array} array The array to flatten.
7367      * @returns {Array} Returns the new flattened array.
7368      * @example
7369      *
7370      * _.flattenDeep([1, [2, [3, [4]], 5]]);
7371      * // => [1, 2, 3, 4, 5]
7372      */
7373     function flattenDeep(array) {
7374       var length = array == null ? 0 : array.length;
7375       return length ? baseFlatten(array, INFINITY) : [];
7376     }
7377
7378     /**
7379      * Recursively flatten `array` up to `depth` times.
7380      *
7381      * @static
7382      * @memberOf _
7383      * @since 4.4.0
7384      * @category Array
7385      * @param {Array} array The array to flatten.
7386      * @param {number} [depth=1] The maximum recursion depth.
7387      * @returns {Array} Returns the new flattened array.
7388      * @example
7389      *
7390      * var array = [1, [2, [3, [4]], 5]];
7391      *
7392      * _.flattenDepth(array, 1);
7393      * // => [1, 2, [3, [4]], 5]
7394      *
7395      * _.flattenDepth(array, 2);
7396      * // => [1, 2, 3, [4], 5]
7397      */
7398     function flattenDepth(array, depth) {
7399       var length = array == null ? 0 : array.length;
7400       if (!length) {
7401         return [];
7402       }
7403       depth = depth === undefined ? 1 : toInteger(depth);
7404       return baseFlatten(array, depth);
7405     }
7406
7407     /**
7408      * The inverse of `_.toPairs`; this method returns an object composed
7409      * from key-value `pairs`.
7410      *
7411      * @static
7412      * @memberOf _
7413      * @since 4.0.0
7414      * @category Array
7415      * @param {Array} pairs The key-value pairs.
7416      * @returns {Object} Returns the new object.
7417      * @example
7418      *
7419      * _.fromPairs([['a', 1], ['b', 2]]);
7420      * // => { 'a': 1, 'b': 2 }
7421      */
7422     function fromPairs(pairs) {
7423       var index = -1,
7424           length = pairs == null ? 0 : pairs.length,
7425           result = {};
7426
7427       while (++index < length) {
7428         var pair = pairs[index];
7429         result[pair[0]] = pair[1];
7430       }
7431       return result;
7432     }
7433
7434     /**
7435      * Gets the first element of `array`.
7436      *
7437      * @static
7438      * @memberOf _
7439      * @since 0.1.0
7440      * @alias first
7441      * @category Array
7442      * @param {Array} array The array to query.
7443      * @returns {*} Returns the first element of `array`.
7444      * @example
7445      *
7446      * _.head([1, 2, 3]);
7447      * // => 1
7448      *
7449      * _.head([]);
7450      * // => undefined
7451      */
7452     function head(array) {
7453       return (array && array.length) ? array[0] : undefined;
7454     }
7455
7456     /**
7457      * Gets the index at which the first occurrence of `value` is found in `array`
7458      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7459      * for equality comparisons. If `fromIndex` is negative, it's used as the
7460      * offset from the end of `array`.
7461      *
7462      * @static
7463      * @memberOf _
7464      * @since 0.1.0
7465      * @category Array
7466      * @param {Array} array The array to inspect.
7467      * @param {*} value The value to search for.
7468      * @param {number} [fromIndex=0] The index to search from.
7469      * @returns {number} Returns the index of the matched value, else `-1`.
7470      * @example
7471      *
7472      * _.indexOf([1, 2, 1, 2], 2);
7473      * // => 1
7474      *
7475      * // Search from the `fromIndex`.
7476      * _.indexOf([1, 2, 1, 2], 2, 2);
7477      * // => 3
7478      */
7479     function indexOf(array, value, fromIndex) {
7480       var length = array == null ? 0 : array.length;
7481       if (!length) {
7482         return -1;
7483       }
7484       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7485       if (index < 0) {
7486         index = nativeMax(length + index, 0);
7487       }
7488       return baseIndexOf(array, value, index);
7489     }
7490
7491     /**
7492      * Gets all but the last element of `array`.
7493      *
7494      * @static
7495      * @memberOf _
7496      * @since 0.1.0
7497      * @category Array
7498      * @param {Array} array The array to query.
7499      * @returns {Array} Returns the slice of `array`.
7500      * @example
7501      *
7502      * _.initial([1, 2, 3]);
7503      * // => [1, 2]
7504      */
7505     function initial(array) {
7506       var length = array == null ? 0 : array.length;
7507       return length ? baseSlice(array, 0, -1) : [];
7508     }
7509
7510     /**
7511      * Creates an array of unique values that are included in all given arrays
7512      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7513      * for equality comparisons. The order and references of result values are
7514      * determined by the first array.
7515      *
7516      * @static
7517      * @memberOf _
7518      * @since 0.1.0
7519      * @category Array
7520      * @param {...Array} [arrays] The arrays to inspect.
7521      * @returns {Array} Returns the new array of intersecting values.
7522      * @example
7523      *
7524      * _.intersection([2, 1], [2, 3]);
7525      * // => [2]
7526      */
7527     var intersection = baseRest(function(arrays) {
7528       var mapped = arrayMap(arrays, castArrayLikeObject);
7529       return (mapped.length && mapped[0] === arrays[0])
7530         ? baseIntersection(mapped)
7531         : [];
7532     });
7533
7534     /**
7535      * This method is like `_.intersection` except that it accepts `iteratee`
7536      * which is invoked for each element of each `arrays` to generate the criterion
7537      * by which they're compared. The order and references of result values are
7538      * determined by the first array. The iteratee is invoked with one argument:
7539      * (value).
7540      *
7541      * @static
7542      * @memberOf _
7543      * @since 4.0.0
7544      * @category Array
7545      * @param {...Array} [arrays] The arrays to inspect.
7546      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7547      * @returns {Array} Returns the new array of intersecting values.
7548      * @example
7549      *
7550      * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7551      * // => [2.1]
7552      *
7553      * // The `_.property` iteratee shorthand.
7554      * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
7555      * // => [{ 'x': 1 }]
7556      */
7557     var intersectionBy = baseRest(function(arrays) {
7558       var iteratee = last(arrays),
7559           mapped = arrayMap(arrays, castArrayLikeObject);
7560
7561       if (iteratee === last(mapped)) {
7562         iteratee = undefined;
7563       } else {
7564         mapped.pop();
7565       }
7566       return (mapped.length && mapped[0] === arrays[0])
7567         ? baseIntersection(mapped, getIteratee(iteratee, 2))
7568         : [];
7569     });
7570
7571     /**
7572      * This method is like `_.intersection` except that it accepts `comparator`
7573      * which is invoked to compare elements of `arrays`. The order and references
7574      * of result values are determined by the first array. The comparator is
7575      * invoked with two arguments: (arrVal, othVal).
7576      *
7577      * @static
7578      * @memberOf _
7579      * @since 4.0.0
7580      * @category Array
7581      * @param {...Array} [arrays] The arrays to inspect.
7582      * @param {Function} [comparator] The comparator invoked per element.
7583      * @returns {Array} Returns the new array of intersecting values.
7584      * @example
7585      *
7586      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7587      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
7588      *
7589      * _.intersectionWith(objects, others, _.isEqual);
7590      * // => [{ 'x': 1, 'y': 2 }]
7591      */
7592     var intersectionWith = baseRest(function(arrays) {
7593       var comparator = last(arrays),
7594           mapped = arrayMap(arrays, castArrayLikeObject);
7595
7596       comparator = typeof comparator == 'function' ? comparator : undefined;
7597       if (comparator) {
7598         mapped.pop();
7599       }
7600       return (mapped.length && mapped[0] === arrays[0])
7601         ? baseIntersection(mapped, undefined, comparator)
7602         : [];
7603     });
7604
7605     /**
7606      * Converts all elements in `array` into a string separated by `separator`.
7607      *
7608      * @static
7609      * @memberOf _
7610      * @since 4.0.0
7611      * @category Array
7612      * @param {Array} array The array to convert.
7613      * @param {string} [separator=','] The element separator.
7614      * @returns {string} Returns the joined string.
7615      * @example
7616      *
7617      * _.join(['a', 'b', 'c'], '~');
7618      * // => 'a~b~c'
7619      */
7620     function join(array, separator) {
7621       return array == null ? '' : nativeJoin.call(array, separator);
7622     }
7623
7624     /**
7625      * Gets the last element of `array`.
7626      *
7627      * @static
7628      * @memberOf _
7629      * @since 0.1.0
7630      * @category Array
7631      * @param {Array} array The array to query.
7632      * @returns {*} Returns the last element of `array`.
7633      * @example
7634      *
7635      * _.last([1, 2, 3]);
7636      * // => 3
7637      */
7638     function last(array) {
7639       var length = array == null ? 0 : array.length;
7640       return length ? array[length - 1] : undefined;
7641     }
7642
7643     /**
7644      * This method is like `_.indexOf` except that it iterates over elements of
7645      * `array` from right to left.
7646      *
7647      * @static
7648      * @memberOf _
7649      * @since 0.1.0
7650      * @category Array
7651      * @param {Array} array The array to inspect.
7652      * @param {*} value The value to search for.
7653      * @param {number} [fromIndex=array.length-1] The index to search from.
7654      * @returns {number} Returns the index of the matched value, else `-1`.
7655      * @example
7656      *
7657      * _.lastIndexOf([1, 2, 1, 2], 2);
7658      * // => 3
7659      *
7660      * // Search from the `fromIndex`.
7661      * _.lastIndexOf([1, 2, 1, 2], 2, 2);
7662      * // => 1
7663      */
7664     function lastIndexOf(array, value, fromIndex) {
7665       var length = array == null ? 0 : array.length;
7666       if (!length) {
7667         return -1;
7668       }
7669       var index = length;
7670       if (fromIndex !== undefined) {
7671         index = toInteger(fromIndex);
7672         index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
7673       }
7674       return value === value
7675         ? strictLastIndexOf(array, value, index)
7676         : baseFindIndex(array, baseIsNaN, index, true);
7677     }
7678
7679     /**
7680      * Gets the element at index `n` of `array`. If `n` is negative, the nth
7681      * element from the end is returned.
7682      *
7683      * @static
7684      * @memberOf _
7685      * @since 4.11.0
7686      * @category Array
7687      * @param {Array} array The array to query.
7688      * @param {number} [n=0] The index of the element to return.
7689      * @returns {*} Returns the nth element of `array`.
7690      * @example
7691      *
7692      * var array = ['a', 'b', 'c', 'd'];
7693      *
7694      * _.nth(array, 1);
7695      * // => 'b'
7696      *
7697      * _.nth(array, -2);
7698      * // => 'c';
7699      */
7700     function nth(array, n) {
7701       return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
7702     }
7703
7704     /**
7705      * Removes all given values from `array` using
7706      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7707      * for equality comparisons.
7708      *
7709      * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
7710      * to remove elements from an array by predicate.
7711      *
7712      * @static
7713      * @memberOf _
7714      * @since 2.0.0
7715      * @category Array
7716      * @param {Array} array The array to modify.
7717      * @param {...*} [values] The values to remove.
7718      * @returns {Array} Returns `array`.
7719      * @example
7720      *
7721      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7722      *
7723      * _.pull(array, 'a', 'c');
7724      * console.log(array);
7725      * // => ['b', 'b']
7726      */
7727     var pull = baseRest(pullAll);
7728
7729     /**
7730      * This method is like `_.pull` except that it accepts an array of values to remove.
7731      *
7732      * **Note:** Unlike `_.difference`, this method mutates `array`.
7733      *
7734      * @static
7735      * @memberOf _
7736      * @since 4.0.0
7737      * @category Array
7738      * @param {Array} array The array to modify.
7739      * @param {Array} values The values to remove.
7740      * @returns {Array} Returns `array`.
7741      * @example
7742      *
7743      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7744      *
7745      * _.pullAll(array, ['a', 'c']);
7746      * console.log(array);
7747      * // => ['b', 'b']
7748      */
7749     function pullAll(array, values) {
7750       return (array && array.length && values && values.length)
7751         ? basePullAll(array, values)
7752         : array;
7753     }
7754
7755     /**
7756      * This method is like `_.pullAll` except that it accepts `iteratee` which is
7757      * invoked for each element of `array` and `values` to generate the criterion
7758      * by which they're compared. The iteratee is invoked with one argument: (value).
7759      *
7760      * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
7761      *
7762      * @static
7763      * @memberOf _
7764      * @since 4.0.0
7765      * @category Array
7766      * @param {Array} array The array to modify.
7767      * @param {Array} values The values to remove.
7768      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7769      * @returns {Array} Returns `array`.
7770      * @example
7771      *
7772      * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
7773      *
7774      * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
7775      * console.log(array);
7776      * // => [{ 'x': 2 }]
7777      */
7778     function pullAllBy(array, values, iteratee) {
7779       return (array && array.length && values && values.length)
7780         ? basePullAll(array, values, getIteratee(iteratee, 2))
7781         : array;
7782     }
7783
7784     /**
7785      * This method is like `_.pullAll` except that it accepts `comparator` which
7786      * is invoked to compare elements of `array` to `values`. The comparator is
7787      * invoked with two arguments: (arrVal, othVal).
7788      *
7789      * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
7790      *
7791      * @static
7792      * @memberOf _
7793      * @since 4.6.0
7794      * @category Array
7795      * @param {Array} array The array to modify.
7796      * @param {Array} values The values to remove.
7797      * @param {Function} [comparator] The comparator invoked per element.
7798      * @returns {Array} Returns `array`.
7799      * @example
7800      *
7801      * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
7802      *
7803      * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
7804      * console.log(array);
7805      * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
7806      */
7807     function pullAllWith(array, values, comparator) {
7808       return (array && array.length && values && values.length)
7809         ? basePullAll(array, values, undefined, comparator)
7810         : array;
7811     }
7812
7813     /**
7814      * Removes elements from `array` corresponding to `indexes` and returns an
7815      * array of removed elements.
7816      *
7817      * **Note:** Unlike `_.at`, this method mutates `array`.
7818      *
7819      * @static
7820      * @memberOf _
7821      * @since 3.0.0
7822      * @category Array
7823      * @param {Array} array The array to modify.
7824      * @param {...(number|number[])} [indexes] The indexes of elements to remove.
7825      * @returns {Array} Returns the new array of removed elements.
7826      * @example
7827      *
7828      * var array = ['a', 'b', 'c', 'd'];
7829      * var pulled = _.pullAt(array, [1, 3]);
7830      *
7831      * console.log(array);
7832      * // => ['a', 'c']
7833      *
7834      * console.log(pulled);
7835      * // => ['b', 'd']
7836      */
7837     var pullAt = flatRest(function(array, indexes) {
7838       var length = array == null ? 0 : array.length,
7839           result = baseAt(array, indexes);
7840
7841       basePullAt(array, arrayMap(indexes, function(index) {
7842         return isIndex(index, length) ? +index : index;
7843       }).sort(compareAscending));
7844
7845       return result;
7846     });
7847
7848     /**
7849      * Removes all elements from `array` that `predicate` returns truthy for
7850      * and returns an array of the removed elements. The predicate is invoked
7851      * with three arguments: (value, index, array).
7852      *
7853      * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
7854      * to pull elements from an array by value.
7855      *
7856      * @static
7857      * @memberOf _
7858      * @since 2.0.0
7859      * @category Array
7860      * @param {Array} array The array to modify.
7861      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7862      * @returns {Array} Returns the new array of removed elements.
7863      * @example
7864      *
7865      * var array = [1, 2, 3, 4];
7866      * var evens = _.remove(array, function(n) {
7867      *   return n % 2 == 0;
7868      * });
7869      *
7870      * console.log(array);
7871      * // => [1, 3]
7872      *
7873      * console.log(evens);
7874      * // => [2, 4]
7875      */
7876     function remove(array, predicate) {
7877       var result = [];
7878       if (!(array && array.length)) {
7879         return result;
7880       }
7881       var index = -1,
7882           indexes = [],
7883           length = array.length;
7884
7885       predicate = getIteratee(predicate, 3);
7886       while (++index < length) {
7887         var value = array[index];
7888         if (predicate(value, index, array)) {
7889           result.push(value);
7890           indexes.push(index);
7891         }
7892       }
7893       basePullAt(array, indexes);
7894       return result;
7895     }
7896
7897     /**
7898      * Reverses `array` so that the first element becomes the last, the second
7899      * element becomes the second to last, and so on.
7900      *
7901      * **Note:** This method mutates `array` and is based on
7902      * [`Array#reverse`](https://mdn.io/Array/reverse).
7903      *
7904      * @static
7905      * @memberOf _
7906      * @since 4.0.0
7907      * @category Array
7908      * @param {Array} array The array to modify.
7909      * @returns {Array} Returns `array`.
7910      * @example
7911      *
7912      * var array = [1, 2, 3];
7913      *
7914      * _.reverse(array);
7915      * // => [3, 2, 1]
7916      *
7917      * console.log(array);
7918      * // => [3, 2, 1]
7919      */
7920     function reverse(array) {
7921       return array == null ? array : nativeReverse.call(array);
7922     }
7923
7924     /**
7925      * Creates a slice of `array` from `start` up to, but not including, `end`.
7926      *
7927      * **Note:** This method is used instead of
7928      * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
7929      * returned.
7930      *
7931      * @static
7932      * @memberOf _
7933      * @since 3.0.0
7934      * @category Array
7935      * @param {Array} array The array to slice.
7936      * @param {number} [start=0] The start position.
7937      * @param {number} [end=array.length] The end position.
7938      * @returns {Array} Returns the slice of `array`.
7939      */
7940     function slice(array, start, end) {
7941       var length = array == null ? 0 : array.length;
7942       if (!length) {
7943         return [];
7944       }
7945       if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
7946         start = 0;
7947         end = length;
7948       }
7949       else {
7950         start = start == null ? 0 : toInteger(start);
7951         end = end === undefined ? length : toInteger(end);
7952       }
7953       return baseSlice(array, start, end);
7954     }
7955
7956     /**
7957      * Uses a binary search to determine the lowest index at which `value`
7958      * should be inserted into `array` in order to maintain its sort order.
7959      *
7960      * @static
7961      * @memberOf _
7962      * @since 0.1.0
7963      * @category Array
7964      * @param {Array} array The sorted array to inspect.
7965      * @param {*} value The value to evaluate.
7966      * @returns {number} Returns the index at which `value` should be inserted
7967      *  into `array`.
7968      * @example
7969      *
7970      * _.sortedIndex([30, 50], 40);
7971      * // => 1
7972      */
7973     function sortedIndex(array, value) {
7974       return baseSortedIndex(array, value);
7975     }
7976
7977     /**
7978      * This method is like `_.sortedIndex` except that it accepts `iteratee`
7979      * which is invoked for `value` and each element of `array` to compute their
7980      * sort ranking. The iteratee is invoked with one argument: (value).
7981      *
7982      * @static
7983      * @memberOf _
7984      * @since 4.0.0
7985      * @category Array
7986      * @param {Array} array The sorted array to inspect.
7987      * @param {*} value The value to evaluate.
7988      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7989      * @returns {number} Returns the index at which `value` should be inserted
7990      *  into `array`.
7991      * @example
7992      *
7993      * var objects = [{ 'x': 4 }, { 'x': 5 }];
7994      *
7995      * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
7996      * // => 0
7997      *
7998      * // The `_.property` iteratee shorthand.
7999      * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
8000      * // => 0
8001      */
8002     function sortedIndexBy(array, value, iteratee) {
8003       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
8004     }
8005
8006     /**
8007      * This method is like `_.indexOf` except that it performs a binary
8008      * search on a sorted `array`.
8009      *
8010      * @static
8011      * @memberOf _
8012      * @since 4.0.0
8013      * @category Array
8014      * @param {Array} array The array to inspect.
8015      * @param {*} value The value to search for.
8016      * @returns {number} Returns the index of the matched value, else `-1`.
8017      * @example
8018      *
8019      * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
8020      * // => 1
8021      */
8022     function sortedIndexOf(array, value) {
8023       var length = array == null ? 0 : array.length;
8024       if (length) {
8025         var index = baseSortedIndex(array, value);
8026         if (index < length && eq(array[index], value)) {
8027           return index;
8028         }
8029       }
8030       return -1;
8031     }
8032
8033     /**
8034      * This method is like `_.sortedIndex` except that it returns the highest
8035      * index at which `value` should be inserted into `array` in order to
8036      * maintain its sort order.
8037      *
8038      * @static
8039      * @memberOf _
8040      * @since 3.0.0
8041      * @category Array
8042      * @param {Array} array The sorted array to inspect.
8043      * @param {*} value The value to evaluate.
8044      * @returns {number} Returns the index at which `value` should be inserted
8045      *  into `array`.
8046      * @example
8047      *
8048      * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
8049      * // => 4
8050      */
8051     function sortedLastIndex(array, value) {
8052       return baseSortedIndex(array, value, true);
8053     }
8054
8055     /**
8056      * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
8057      * which is invoked for `value` and each element of `array` to compute their
8058      * sort ranking. The iteratee is invoked with one argument: (value).
8059      *
8060      * @static
8061      * @memberOf _
8062      * @since 4.0.0
8063      * @category Array
8064      * @param {Array} array The sorted array to inspect.
8065      * @param {*} value The value to evaluate.
8066      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8067      * @returns {number} Returns the index at which `value` should be inserted
8068      *  into `array`.
8069      * @example
8070      *
8071      * var objects = [{ 'x': 4 }, { 'x': 5 }];
8072      *
8073      * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8074      * // => 1
8075      *
8076      * // The `_.property` iteratee shorthand.
8077      * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
8078      * // => 1
8079      */
8080     function sortedLastIndexBy(array, value, iteratee) {
8081       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
8082     }
8083
8084     /**
8085      * This method is like `_.lastIndexOf` except that it performs a binary
8086      * search on a sorted `array`.
8087      *
8088      * @static
8089      * @memberOf _
8090      * @since 4.0.0
8091      * @category Array
8092      * @param {Array} array The array to inspect.
8093      * @param {*} value The value to search for.
8094      * @returns {number} Returns the index of the matched value, else `-1`.
8095      * @example
8096      *
8097      * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
8098      * // => 3
8099      */
8100     function sortedLastIndexOf(array, value) {
8101       var length = array == null ? 0 : array.length;
8102       if (length) {
8103         var index = baseSortedIndex(array, value, true) - 1;
8104         if (eq(array[index], value)) {
8105           return index;
8106         }
8107       }
8108       return -1;
8109     }
8110
8111     /**
8112      * This method is like `_.uniq` except that it's designed and optimized
8113      * for sorted arrays.
8114      *
8115      * @static
8116      * @memberOf _
8117      * @since 4.0.0
8118      * @category Array
8119      * @param {Array} array The array to inspect.
8120      * @returns {Array} Returns the new duplicate free array.
8121      * @example
8122      *
8123      * _.sortedUniq([1, 1, 2]);
8124      * // => [1, 2]
8125      */
8126     function sortedUniq(array) {
8127       return (array && array.length)
8128         ? baseSortedUniq(array)
8129         : [];
8130     }
8131
8132     /**
8133      * This method is like `_.uniqBy` except that it's designed and optimized
8134      * for sorted arrays.
8135      *
8136      * @static
8137      * @memberOf _
8138      * @since 4.0.0
8139      * @category Array
8140      * @param {Array} array The array to inspect.
8141      * @param {Function} [iteratee] The iteratee invoked per element.
8142      * @returns {Array} Returns the new duplicate free array.
8143      * @example
8144      *
8145      * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
8146      * // => [1.1, 2.3]
8147      */
8148     function sortedUniqBy(array, iteratee) {
8149       return (array && array.length)
8150         ? baseSortedUniq(array, getIteratee(iteratee, 2))
8151         : [];
8152     }
8153
8154     /**
8155      * Gets all but the first element of `array`.
8156      *
8157      * @static
8158      * @memberOf _
8159      * @since 4.0.0
8160      * @category Array
8161      * @param {Array} array The array to query.
8162      * @returns {Array} Returns the slice of `array`.
8163      * @example
8164      *
8165      * _.tail([1, 2, 3]);
8166      * // => [2, 3]
8167      */
8168     function tail(array) {
8169       var length = array == null ? 0 : array.length;
8170       return length ? baseSlice(array, 1, length) : [];
8171     }
8172
8173     /**
8174      * Creates a slice of `array` with `n` elements taken from the beginning.
8175      *
8176      * @static
8177      * @memberOf _
8178      * @since 0.1.0
8179      * @category Array
8180      * @param {Array} array The array to query.
8181      * @param {number} [n=1] The number of elements to take.
8182      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8183      * @returns {Array} Returns the slice of `array`.
8184      * @example
8185      *
8186      * _.take([1, 2, 3]);
8187      * // => [1]
8188      *
8189      * _.take([1, 2, 3], 2);
8190      * // => [1, 2]
8191      *
8192      * _.take([1, 2, 3], 5);
8193      * // => [1, 2, 3]
8194      *
8195      * _.take([1, 2, 3], 0);
8196      * // => []
8197      */
8198     function take(array, n, guard) {
8199       if (!(array && array.length)) {
8200         return [];
8201       }
8202       n = (guard || n === undefined) ? 1 : toInteger(n);
8203       return baseSlice(array, 0, n < 0 ? 0 : n);
8204     }
8205
8206     /**
8207      * Creates a slice of `array` with `n` elements taken from the end.
8208      *
8209      * @static
8210      * @memberOf _
8211      * @since 3.0.0
8212      * @category Array
8213      * @param {Array} array The array to query.
8214      * @param {number} [n=1] The number of elements to take.
8215      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8216      * @returns {Array} Returns the slice of `array`.
8217      * @example
8218      *
8219      * _.takeRight([1, 2, 3]);
8220      * // => [3]
8221      *
8222      * _.takeRight([1, 2, 3], 2);
8223      * // => [2, 3]
8224      *
8225      * _.takeRight([1, 2, 3], 5);
8226      * // => [1, 2, 3]
8227      *
8228      * _.takeRight([1, 2, 3], 0);
8229      * // => []
8230      */
8231     function takeRight(array, n, guard) {
8232       var length = array == null ? 0 : array.length;
8233       if (!length) {
8234         return [];
8235       }
8236       n = (guard || n === undefined) ? 1 : toInteger(n);
8237       n = length - n;
8238       return baseSlice(array, n < 0 ? 0 : n, length);
8239     }
8240
8241     /**
8242      * Creates a slice of `array` with elements taken from the end. Elements are
8243      * taken until `predicate` returns falsey. The predicate is invoked with
8244      * three arguments: (value, index, array).
8245      *
8246      * @static
8247      * @memberOf _
8248      * @since 3.0.0
8249      * @category Array
8250      * @param {Array} array The array to query.
8251      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8252      * @returns {Array} Returns the slice of `array`.
8253      * @example
8254      *
8255      * var users = [
8256      *   { 'user': 'barney',  'active': true },
8257      *   { 'user': 'fred',    'active': false },
8258      *   { 'user': 'pebbles', 'active': false }
8259      * ];
8260      *
8261      * _.takeRightWhile(users, function(o) { return !o.active; });
8262      * // => objects for ['fred', 'pebbles']
8263      *
8264      * // The `_.matches` iteratee shorthand.
8265      * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
8266      * // => objects for ['pebbles']
8267      *
8268      * // The `_.matchesProperty` iteratee shorthand.
8269      * _.takeRightWhile(users, ['active', false]);
8270      * // => objects for ['fred', 'pebbles']
8271      *
8272      * // The `_.property` iteratee shorthand.
8273      * _.takeRightWhile(users, 'active');
8274      * // => []
8275      */
8276     function takeRightWhile(array, predicate) {
8277       return (array && array.length)
8278         ? baseWhile(array, getIteratee(predicate, 3), false, true)
8279         : [];
8280     }
8281
8282     /**
8283      * Creates a slice of `array` with elements taken from the beginning. Elements
8284      * are taken until `predicate` returns falsey. The predicate is invoked with
8285      * three arguments: (value, index, array).
8286      *
8287      * @static
8288      * @memberOf _
8289      * @since 3.0.0
8290      * @category Array
8291      * @param {Array} array The array to query.
8292      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8293      * @returns {Array} Returns the slice of `array`.
8294      * @example
8295      *
8296      * var users = [
8297      *   { 'user': 'barney',  'active': false },
8298      *   { 'user': 'fred',    'active': false},
8299      *   { 'user': 'pebbles', 'active': true }
8300      * ];
8301      *
8302      * _.takeWhile(users, function(o) { return !o.active; });
8303      * // => objects for ['barney', 'fred']
8304      *
8305      * // The `_.matches` iteratee shorthand.
8306      * _.takeWhile(users, { 'user': 'barney', 'active': false });
8307      * // => objects for ['barney']
8308      *
8309      * // The `_.matchesProperty` iteratee shorthand.
8310      * _.takeWhile(users, ['active', false]);
8311      * // => objects for ['barney', 'fred']
8312      *
8313      * // The `_.property` iteratee shorthand.
8314      * _.takeWhile(users, 'active');
8315      * // => []
8316      */
8317     function takeWhile(array, predicate) {
8318       return (array && array.length)
8319         ? baseWhile(array, getIteratee(predicate, 3))
8320         : [];
8321     }
8322
8323     /**
8324      * Creates an array of unique values, in order, from all given arrays using
8325      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8326      * for equality comparisons.
8327      *
8328      * @static
8329      * @memberOf _
8330      * @since 0.1.0
8331      * @category Array
8332      * @param {...Array} [arrays] The arrays to inspect.
8333      * @returns {Array} Returns the new array of combined values.
8334      * @example
8335      *
8336      * _.union([2], [1, 2]);
8337      * // => [2, 1]
8338      */
8339     var union = baseRest(function(arrays) {
8340       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
8341     });
8342
8343     /**
8344      * This method is like `_.union` except that it accepts `iteratee` which is
8345      * invoked for each element of each `arrays` to generate the criterion by
8346      * which uniqueness is computed. Result values are chosen from the first
8347      * array in which the value occurs. The iteratee is invoked with one argument:
8348      * (value).
8349      *
8350      * @static
8351      * @memberOf _
8352      * @since 4.0.0
8353      * @category Array
8354      * @param {...Array} [arrays] The arrays to inspect.
8355      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8356      * @returns {Array} Returns the new array of combined values.
8357      * @example
8358      *
8359      * _.unionBy([2.1], [1.2, 2.3], Math.floor);
8360      * // => [2.1, 1.2]
8361      *
8362      * // The `_.property` iteratee shorthand.
8363      * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8364      * // => [{ 'x': 1 }, { 'x': 2 }]
8365      */
8366     var unionBy = baseRest(function(arrays) {
8367       var iteratee = last(arrays);
8368       if (isArrayLikeObject(iteratee)) {
8369         iteratee = undefined;
8370       }
8371       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
8372     });
8373
8374     /**
8375      * This method is like `_.union` except that it accepts `comparator` which
8376      * is invoked to compare elements of `arrays`. Result values are chosen from
8377      * the first array in which the value occurs. The comparator is invoked
8378      * with two arguments: (arrVal, othVal).
8379      *
8380      * @static
8381      * @memberOf _
8382      * @since 4.0.0
8383      * @category Array
8384      * @param {...Array} [arrays] The arrays to inspect.
8385      * @param {Function} [comparator] The comparator invoked per element.
8386      * @returns {Array} Returns the new array of combined values.
8387      * @example
8388      *
8389      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8390      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8391      *
8392      * _.unionWith(objects, others, _.isEqual);
8393      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8394      */
8395     var unionWith = baseRest(function(arrays) {
8396       var comparator = last(arrays);
8397       comparator = typeof comparator == 'function' ? comparator : undefined;
8398       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
8399     });
8400
8401     /**
8402      * Creates a duplicate-free version of an array, using
8403      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8404      * for equality comparisons, in which only the first occurrence of each element
8405      * is kept. The order of result values is determined by the order they occur
8406      * in the array.
8407      *
8408      * @static
8409      * @memberOf _
8410      * @since 0.1.0
8411      * @category Array
8412      * @param {Array} array The array to inspect.
8413      * @returns {Array} Returns the new duplicate free array.
8414      * @example
8415      *
8416      * _.uniq([2, 1, 2]);
8417      * // => [2, 1]
8418      */
8419     function uniq(array) {
8420       return (array && array.length) ? baseUniq(array) : [];
8421     }
8422
8423     /**
8424      * This method is like `_.uniq` except that it accepts `iteratee` which is
8425      * invoked for each element in `array` to generate the criterion by which
8426      * uniqueness is computed. The order of result values is determined by the
8427      * order they occur in the array. The iteratee is invoked with one argument:
8428      * (value).
8429      *
8430      * @static
8431      * @memberOf _
8432      * @since 4.0.0
8433      * @category Array
8434      * @param {Array} array The array to inspect.
8435      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8436      * @returns {Array} Returns the new duplicate free array.
8437      * @example
8438      *
8439      * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
8440      * // => [2.1, 1.2]
8441      *
8442      * // The `_.property` iteratee shorthand.
8443      * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
8444      * // => [{ 'x': 1 }, { 'x': 2 }]
8445      */
8446     function uniqBy(array, iteratee) {
8447       return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
8448     }
8449
8450     /**
8451      * This method is like `_.uniq` except that it accepts `comparator` which
8452      * is invoked to compare elements of `array`. The order of result values is
8453      * determined by the order they occur in the array.The comparator is invoked
8454      * with two arguments: (arrVal, othVal).
8455      *
8456      * @static
8457      * @memberOf _
8458      * @since 4.0.0
8459      * @category Array
8460      * @param {Array} array The array to inspect.
8461      * @param {Function} [comparator] The comparator invoked per element.
8462      * @returns {Array} Returns the new duplicate free array.
8463      * @example
8464      *
8465      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
8466      *
8467      * _.uniqWith(objects, _.isEqual);
8468      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
8469      */
8470     function uniqWith(array, comparator) {
8471       comparator = typeof comparator == 'function' ? comparator : undefined;
8472       return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
8473     }
8474
8475     /**
8476      * This method is like `_.zip` except that it accepts an array of grouped
8477      * elements and creates an array regrouping the elements to their pre-zip
8478      * configuration.
8479      *
8480      * @static
8481      * @memberOf _
8482      * @since 1.2.0
8483      * @category Array
8484      * @param {Array} array The array of grouped elements to process.
8485      * @returns {Array} Returns the new array of regrouped elements.
8486      * @example
8487      *
8488      * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
8489      * // => [['a', 1, true], ['b', 2, false]]
8490      *
8491      * _.unzip(zipped);
8492      * // => [['a', 'b'], [1, 2], [true, false]]
8493      */
8494     function unzip(array) {
8495       if (!(array && array.length)) {
8496         return [];
8497       }
8498       var length = 0;
8499       array = arrayFilter(array, function(group) {
8500         if (isArrayLikeObject(group)) {
8501           length = nativeMax(group.length, length);
8502           return true;
8503         }
8504       });
8505       return baseTimes(length, function(index) {
8506         return arrayMap(array, baseProperty(index));
8507       });
8508     }
8509
8510     /**
8511      * This method is like `_.unzip` except that it accepts `iteratee` to specify
8512      * how regrouped values should be combined. The iteratee is invoked with the
8513      * elements of each group: (...group).
8514      *
8515      * @static
8516      * @memberOf _
8517      * @since 3.8.0
8518      * @category Array
8519      * @param {Array} array The array of grouped elements to process.
8520      * @param {Function} [iteratee=_.identity] The function to combine
8521      *  regrouped values.
8522      * @returns {Array} Returns the new array of regrouped elements.
8523      * @example
8524      *
8525      * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
8526      * // => [[1, 10, 100], [2, 20, 200]]
8527      *
8528      * _.unzipWith(zipped, _.add);
8529      * // => [3, 30, 300]
8530      */
8531     function unzipWith(array, iteratee) {
8532       if (!(array && array.length)) {
8533         return [];
8534       }
8535       var result = unzip(array);
8536       if (iteratee == null) {
8537         return result;
8538       }
8539       return arrayMap(result, function(group) {
8540         return apply(iteratee, undefined, group);
8541       });
8542     }
8543
8544     /**
8545      * Creates an array excluding all given values using
8546      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8547      * for equality comparisons.
8548      *
8549      * **Note:** Unlike `_.pull`, this method returns a new array.
8550      *
8551      * @static
8552      * @memberOf _
8553      * @since 0.1.0
8554      * @category Array
8555      * @param {Array} array The array to inspect.
8556      * @param {...*} [values] The values to exclude.
8557      * @returns {Array} Returns the new array of filtered values.
8558      * @see _.difference, _.xor
8559      * @example
8560      *
8561      * _.without([2, 1, 2, 3], 1, 2);
8562      * // => [3]
8563      */
8564     var without = baseRest(function(array, values) {
8565       return isArrayLikeObject(array)
8566         ? baseDifference(array, values)
8567         : [];
8568     });
8569
8570     /**
8571      * Creates an array of unique values that is the
8572      * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
8573      * of the given arrays. The order of result values is determined by the order
8574      * they occur in the arrays.
8575      *
8576      * @static
8577      * @memberOf _
8578      * @since 2.4.0
8579      * @category Array
8580      * @param {...Array} [arrays] The arrays to inspect.
8581      * @returns {Array} Returns the new array of filtered values.
8582      * @see _.difference, _.without
8583      * @example
8584      *
8585      * _.xor([2, 1], [2, 3]);
8586      * // => [1, 3]
8587      */
8588     var xor = baseRest(function(arrays) {
8589       return baseXor(arrayFilter(arrays, isArrayLikeObject));
8590     });
8591
8592     /**
8593      * This method is like `_.xor` except that it accepts `iteratee` which is
8594      * invoked for each element of each `arrays` to generate the criterion by
8595      * which by which they're compared. The order of result values is determined
8596      * by the order they occur in the arrays. The iteratee is invoked with one
8597      * argument: (value).
8598      *
8599      * @static
8600      * @memberOf _
8601      * @since 4.0.0
8602      * @category Array
8603      * @param {...Array} [arrays] The arrays to inspect.
8604      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8605      * @returns {Array} Returns the new array of filtered values.
8606      * @example
8607      *
8608      * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
8609      * // => [1.2, 3.4]
8610      *
8611      * // The `_.property` iteratee shorthand.
8612      * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8613      * // => [{ 'x': 2 }]
8614      */
8615     var xorBy = baseRest(function(arrays) {
8616       var iteratee = last(arrays);
8617       if (isArrayLikeObject(iteratee)) {
8618         iteratee = undefined;
8619       }
8620       return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
8621     });
8622
8623     /**
8624      * This method is like `_.xor` except that it accepts `comparator` which is
8625      * invoked to compare elements of `arrays`. The order of result values is
8626      * determined by the order they occur in the arrays. The comparator is invoked
8627      * with two arguments: (arrVal, othVal).
8628      *
8629      * @static
8630      * @memberOf _
8631      * @since 4.0.0
8632      * @category Array
8633      * @param {...Array} [arrays] The arrays to inspect.
8634      * @param {Function} [comparator] The comparator invoked per element.
8635      * @returns {Array} Returns the new array of filtered values.
8636      * @example
8637      *
8638      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8639      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8640      *
8641      * _.xorWith(objects, others, _.isEqual);
8642      * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8643      */
8644     var xorWith = baseRest(function(arrays) {
8645       var comparator = last(arrays);
8646       comparator = typeof comparator == 'function' ? comparator : undefined;
8647       return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
8648     });
8649
8650     /**
8651      * Creates an array of grouped elements, the first of which contains the
8652      * first elements of the given arrays, the second of which contains the
8653      * second elements of the given arrays, and so on.
8654      *
8655      * @static
8656      * @memberOf _
8657      * @since 0.1.0
8658      * @category Array
8659      * @param {...Array} [arrays] The arrays to process.
8660      * @returns {Array} Returns the new array of grouped elements.
8661      * @example
8662      *
8663      * _.zip(['a', 'b'], [1, 2], [true, false]);
8664      * // => [['a', 1, true], ['b', 2, false]]
8665      */
8666     var zip = baseRest(unzip);
8667
8668     /**
8669      * This method is like `_.fromPairs` except that it accepts two arrays,
8670      * one of property identifiers and one of corresponding values.
8671      *
8672      * @static
8673      * @memberOf _
8674      * @since 0.4.0
8675      * @category Array
8676      * @param {Array} [props=[]] The property identifiers.
8677      * @param {Array} [values=[]] The property values.
8678      * @returns {Object} Returns the new object.
8679      * @example
8680      *
8681      * _.zipObject(['a', 'b'], [1, 2]);
8682      * // => { 'a': 1, 'b': 2 }
8683      */
8684     function zipObject(props, values) {
8685       return baseZipObject(props || [], values || [], assignValue);
8686     }
8687
8688     /**
8689      * This method is like `_.zipObject` except that it supports property paths.
8690      *
8691      * @static
8692      * @memberOf _
8693      * @since 4.1.0
8694      * @category Array
8695      * @param {Array} [props=[]] The property identifiers.
8696      * @param {Array} [values=[]] The property values.
8697      * @returns {Object} Returns the new object.
8698      * @example
8699      *
8700      * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
8701      * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
8702      */
8703     function zipObjectDeep(props, values) {
8704       return baseZipObject(props || [], values || [], baseSet);
8705     }
8706
8707     /**
8708      * This method is like `_.zip` except that it accepts `iteratee` to specify
8709      * how grouped values should be combined. The iteratee is invoked with the
8710      * elements of each group: (...group).
8711      *
8712      * @static
8713      * @memberOf _
8714      * @since 3.8.0
8715      * @category Array
8716      * @param {...Array} [arrays] The arrays to process.
8717      * @param {Function} [iteratee=_.identity] The function to combine
8718      *  grouped values.
8719      * @returns {Array} Returns the new array of grouped elements.
8720      * @example
8721      *
8722      * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
8723      *   return a + b + c;
8724      * });
8725      * // => [111, 222]
8726      */
8727     var zipWith = baseRest(function(arrays) {
8728       var length = arrays.length,
8729           iteratee = length > 1 ? arrays[length - 1] : undefined;
8730
8731       iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
8732       return unzipWith(arrays, iteratee);
8733     });
8734
8735     /*------------------------------------------------------------------------*/
8736
8737     /**
8738      * Creates a `lodash` wrapper instance that wraps `value` with explicit method
8739      * chain sequences enabled. The result of such sequences must be unwrapped
8740      * with `_#value`.
8741      *
8742      * @static
8743      * @memberOf _
8744      * @since 1.3.0
8745      * @category Seq
8746      * @param {*} value The value to wrap.
8747      * @returns {Object} Returns the new `lodash` wrapper instance.
8748      * @example
8749      *
8750      * var users = [
8751      *   { 'user': 'barney',  'age': 36 },
8752      *   { 'user': 'fred',    'age': 40 },
8753      *   { 'user': 'pebbles', 'age': 1 }
8754      * ];
8755      *
8756      * var youngest = _
8757      *   .chain(users)
8758      *   .sortBy('age')
8759      *   .map(function(o) {
8760      *     return o.user + ' is ' + o.age;
8761      *   })
8762      *   .head()
8763      *   .value();
8764      * // => 'pebbles is 1'
8765      */
8766     function chain(value) {
8767       var result = lodash(value);
8768       result.__chain__ = true;
8769       return result;
8770     }
8771
8772     /**
8773      * This method invokes `interceptor` and returns `value`. The interceptor
8774      * is invoked with one argument; (value). The purpose of this method is to
8775      * "tap into" a method chain sequence in order to modify intermediate results.
8776      *
8777      * @static
8778      * @memberOf _
8779      * @since 0.1.0
8780      * @category Seq
8781      * @param {*} value The value to provide to `interceptor`.
8782      * @param {Function} interceptor The function to invoke.
8783      * @returns {*} Returns `value`.
8784      * @example
8785      *
8786      * _([1, 2, 3])
8787      *  .tap(function(array) {
8788      *    // Mutate input array.
8789      *    array.pop();
8790      *  })
8791      *  .reverse()
8792      *  .value();
8793      * // => [2, 1]
8794      */
8795     function tap(value, interceptor) {
8796       interceptor(value);
8797       return value;
8798     }
8799
8800     /**
8801      * This method is like `_.tap` except that it returns the result of `interceptor`.
8802      * The purpose of this method is to "pass thru" values replacing intermediate
8803      * results in a method chain sequence.
8804      *
8805      * @static
8806      * @memberOf _
8807      * @since 3.0.0
8808      * @category Seq
8809      * @param {*} value The value to provide to `interceptor`.
8810      * @param {Function} interceptor The function to invoke.
8811      * @returns {*} Returns the result of `interceptor`.
8812      * @example
8813      *
8814      * _('  abc  ')
8815      *  .chain()
8816      *  .trim()
8817      *  .thru(function(value) {
8818      *    return [value];
8819      *  })
8820      *  .value();
8821      * // => ['abc']
8822      */
8823     function thru(value, interceptor) {
8824       return interceptor(value);
8825     }
8826
8827     /**
8828      * This method is the wrapper version of `_.at`.
8829      *
8830      * @name at
8831      * @memberOf _
8832      * @since 1.0.0
8833      * @category Seq
8834      * @param {...(string|string[])} [paths] The property paths to pick.
8835      * @returns {Object} Returns the new `lodash` wrapper instance.
8836      * @example
8837      *
8838      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
8839      *
8840      * _(object).at(['a[0].b.c', 'a[1]']).value();
8841      * // => [3, 4]
8842      */
8843     var wrapperAt = flatRest(function(paths) {
8844       var length = paths.length,
8845           start = length ? paths[0] : 0,
8846           value = this.__wrapped__,
8847           interceptor = function(object) { return baseAt(object, paths); };
8848
8849       if (length > 1 || this.__actions__.length ||
8850           !(value instanceof LazyWrapper) || !isIndex(start)) {
8851         return this.thru(interceptor);
8852       }
8853       value = value.slice(start, +start + (length ? 1 : 0));
8854       value.__actions__.push({
8855         'func': thru,
8856         'args': [interceptor],
8857         'thisArg': undefined
8858       });
8859       return new LodashWrapper(value, this.__chain__).thru(function(array) {
8860         if (length && !array.length) {
8861           array.push(undefined);
8862         }
8863         return array;
8864       });
8865     });
8866
8867     /**
8868      * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
8869      *
8870      * @name chain
8871      * @memberOf _
8872      * @since 0.1.0
8873      * @category Seq
8874      * @returns {Object} Returns the new `lodash` wrapper instance.
8875      * @example
8876      *
8877      * var users = [
8878      *   { 'user': 'barney', 'age': 36 },
8879      *   { 'user': 'fred',   'age': 40 }
8880      * ];
8881      *
8882      * // A sequence without explicit chaining.
8883      * _(users).head();
8884      * // => { 'user': 'barney', 'age': 36 }
8885      *
8886      * // A sequence with explicit chaining.
8887      * _(users)
8888      *   .chain()
8889      *   .head()
8890      *   .pick('user')
8891      *   .value();
8892      * // => { 'user': 'barney' }
8893      */
8894     function wrapperChain() {
8895       return chain(this);
8896     }
8897
8898     /**
8899      * Executes the chain sequence and returns the wrapped result.
8900      *
8901      * @name commit
8902      * @memberOf _
8903      * @since 3.2.0
8904      * @category Seq
8905      * @returns {Object} Returns the new `lodash` wrapper instance.
8906      * @example
8907      *
8908      * var array = [1, 2];
8909      * var wrapped = _(array).push(3);
8910      *
8911      * console.log(array);
8912      * // => [1, 2]
8913      *
8914      * wrapped = wrapped.commit();
8915      * console.log(array);
8916      * // => [1, 2, 3]
8917      *
8918      * wrapped.last();
8919      * // => 3
8920      *
8921      * console.log(array);
8922      * // => [1, 2, 3]
8923      */
8924     function wrapperCommit() {
8925       return new LodashWrapper(this.value(), this.__chain__);
8926     }
8927
8928     /**
8929      * Gets the next value on a wrapped object following the
8930      * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
8931      *
8932      * @name next
8933      * @memberOf _
8934      * @since 4.0.0
8935      * @category Seq
8936      * @returns {Object} Returns the next iterator value.
8937      * @example
8938      *
8939      * var wrapped = _([1, 2]);
8940      *
8941      * wrapped.next();
8942      * // => { 'done': false, 'value': 1 }
8943      *
8944      * wrapped.next();
8945      * // => { 'done': false, 'value': 2 }
8946      *
8947      * wrapped.next();
8948      * // => { 'done': true, 'value': undefined }
8949      */
8950     function wrapperNext() {
8951       if (this.__values__ === undefined) {
8952         this.__values__ = toArray(this.value());
8953       }
8954       var done = this.__index__ >= this.__values__.length,
8955           value = done ? undefined : this.__values__[this.__index__++];
8956
8957       return { 'done': done, 'value': value };
8958     }
8959
8960     /**
8961      * Enables the wrapper to be iterable.
8962      *
8963      * @name Symbol.iterator
8964      * @memberOf _
8965      * @since 4.0.0
8966      * @category Seq
8967      * @returns {Object} Returns the wrapper object.
8968      * @example
8969      *
8970      * var wrapped = _([1, 2]);
8971      *
8972      * wrapped[Symbol.iterator]() === wrapped;
8973      * // => true
8974      *
8975      * Array.from(wrapped);
8976      * // => [1, 2]
8977      */
8978     function wrapperToIterator() {
8979       return this;
8980     }
8981
8982     /**
8983      * Creates a clone of the chain sequence planting `value` as the wrapped value.
8984      *
8985      * @name plant
8986      * @memberOf _
8987      * @since 3.2.0
8988      * @category Seq
8989      * @param {*} value The value to plant.
8990      * @returns {Object} Returns the new `lodash` wrapper instance.
8991      * @example
8992      *
8993      * function square(n) {
8994      *   return n * n;
8995      * }
8996      *
8997      * var wrapped = _([1, 2]).map(square);
8998      * var other = wrapped.plant([3, 4]);
8999      *
9000      * other.value();
9001      * // => [9, 16]
9002      *
9003      * wrapped.value();
9004      * // => [1, 4]
9005      */
9006     function wrapperPlant(value) {
9007       var result,
9008           parent = this;
9009
9010       while (parent instanceof baseLodash) {
9011         var clone = wrapperClone(parent);
9012         clone.__index__ = 0;
9013         clone.__values__ = undefined;
9014         if (result) {
9015           previous.__wrapped__ = clone;
9016         } else {
9017           result = clone;
9018         }
9019         var previous = clone;
9020         parent = parent.__wrapped__;
9021       }
9022       previous.__wrapped__ = value;
9023       return result;
9024     }
9025
9026     /**
9027      * This method is the wrapper version of `_.reverse`.
9028      *
9029      * **Note:** This method mutates the wrapped array.
9030      *
9031      * @name reverse
9032      * @memberOf _
9033      * @since 0.1.0
9034      * @category Seq
9035      * @returns {Object} Returns the new `lodash` wrapper instance.
9036      * @example
9037      *
9038      * var array = [1, 2, 3];
9039      *
9040      * _(array).reverse().value()
9041      * // => [3, 2, 1]
9042      *
9043      * console.log(array);
9044      * // => [3, 2, 1]
9045      */
9046     function wrapperReverse() {
9047       var value = this.__wrapped__;
9048       if (value instanceof LazyWrapper) {
9049         var wrapped = value;
9050         if (this.__actions__.length) {
9051           wrapped = new LazyWrapper(this);
9052         }
9053         wrapped = wrapped.reverse();
9054         wrapped.__actions__.push({
9055           'func': thru,
9056           'args': [reverse],
9057           'thisArg': undefined
9058         });
9059         return new LodashWrapper(wrapped, this.__chain__);
9060       }
9061       return this.thru(reverse);
9062     }
9063
9064     /**
9065      * Executes the chain sequence to resolve the unwrapped value.
9066      *
9067      * @name value
9068      * @memberOf _
9069      * @since 0.1.0
9070      * @alias toJSON, valueOf
9071      * @category Seq
9072      * @returns {*} Returns the resolved unwrapped value.
9073      * @example
9074      *
9075      * _([1, 2, 3]).value();
9076      * // => [1, 2, 3]
9077      */
9078     function wrapperValue() {
9079       return baseWrapperValue(this.__wrapped__, this.__actions__);
9080     }
9081
9082     /*------------------------------------------------------------------------*/
9083
9084     /**
9085      * Creates an object composed of keys generated from the results of running
9086      * each element of `collection` thru `iteratee`. The corresponding value of
9087      * each key is the number of times the key was returned by `iteratee`. The
9088      * iteratee is invoked with one argument: (value).
9089      *
9090      * @static
9091      * @memberOf _
9092      * @since 0.5.0
9093      * @category Collection
9094      * @param {Array|Object} collection The collection to iterate over.
9095      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9096      * @returns {Object} Returns the composed aggregate object.
9097      * @example
9098      *
9099      * _.countBy([6.1, 4.2, 6.3], Math.floor);
9100      * // => { '4': 1, '6': 2 }
9101      *
9102      * // The `_.property` iteratee shorthand.
9103      * _.countBy(['one', 'two', 'three'], 'length');
9104      * // => { '3': 2, '5': 1 }
9105      */
9106     var countBy = createAggregator(function(result, value, key) {
9107       if (hasOwnProperty.call(result, key)) {
9108         ++result[key];
9109       } else {
9110         baseAssignValue(result, key, 1);
9111       }
9112     });
9113
9114     /**
9115      * Checks if `predicate` returns truthy for **all** elements of `collection`.
9116      * Iteration is stopped once `predicate` returns falsey. The predicate is
9117      * invoked with three arguments: (value, index|key, collection).
9118      *
9119      * **Note:** This method returns `true` for
9120      * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
9121      * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
9122      * elements of empty collections.
9123      *
9124      * @static
9125      * @memberOf _
9126      * @since 0.1.0
9127      * @category Collection
9128      * @param {Array|Object} collection The collection to iterate over.
9129      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9130      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9131      * @returns {boolean} Returns `true` if all elements pass the predicate check,
9132      *  else `false`.
9133      * @example
9134      *
9135      * _.every([true, 1, null, 'yes'], Boolean);
9136      * // => false
9137      *
9138      * var users = [
9139      *   { 'user': 'barney', 'age': 36, 'active': false },
9140      *   { 'user': 'fred',   'age': 40, 'active': false }
9141      * ];
9142      *
9143      * // The `_.matches` iteratee shorthand.
9144      * _.every(users, { 'user': 'barney', 'active': false });
9145      * // => false
9146      *
9147      * // The `_.matchesProperty` iteratee shorthand.
9148      * _.every(users, ['active', false]);
9149      * // => true
9150      *
9151      * // The `_.property` iteratee shorthand.
9152      * _.every(users, 'active');
9153      * // => false
9154      */
9155     function every(collection, predicate, guard) {
9156       var func = isArray(collection) ? arrayEvery : baseEvery;
9157       if (guard && isIterateeCall(collection, predicate, guard)) {
9158         predicate = undefined;
9159       }
9160       return func(collection, getIteratee(predicate, 3));
9161     }
9162
9163     /**
9164      * Iterates over elements of `collection`, returning an array of all elements
9165      * `predicate` returns truthy for. The predicate is invoked with three
9166      * arguments: (value, index|key, collection).
9167      *
9168      * **Note:** Unlike `_.remove`, this method returns a new array.
9169      *
9170      * @static
9171      * @memberOf _
9172      * @since 0.1.0
9173      * @category Collection
9174      * @param {Array|Object} collection The collection to iterate over.
9175      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9176      * @returns {Array} Returns the new filtered array.
9177      * @see _.reject
9178      * @example
9179      *
9180      * var users = [
9181      *   { 'user': 'barney', 'age': 36, 'active': true },
9182      *   { 'user': 'fred',   'age': 40, 'active': false }
9183      * ];
9184      *
9185      * _.filter(users, function(o) { return !o.active; });
9186      * // => objects for ['fred']
9187      *
9188      * // The `_.matches` iteratee shorthand.
9189      * _.filter(users, { 'age': 36, 'active': true });
9190      * // => objects for ['barney']
9191      *
9192      * // The `_.matchesProperty` iteratee shorthand.
9193      * _.filter(users, ['active', false]);
9194      * // => objects for ['fred']
9195      *
9196      * // The `_.property` iteratee shorthand.
9197      * _.filter(users, 'active');
9198      * // => objects for ['barney']
9199      */
9200     function filter(collection, predicate) {
9201       var func = isArray(collection) ? arrayFilter : baseFilter;
9202       return func(collection, getIteratee(predicate, 3));
9203     }
9204
9205     /**
9206      * Iterates over elements of `collection`, returning the first element
9207      * `predicate` returns truthy for. The predicate is invoked with three
9208      * arguments: (value, index|key, collection).
9209      *
9210      * @static
9211      * @memberOf _
9212      * @since 0.1.0
9213      * @category Collection
9214      * @param {Array|Object} collection The collection to inspect.
9215      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9216      * @param {number} [fromIndex=0] The index to search from.
9217      * @returns {*} Returns the matched element, else `undefined`.
9218      * @example
9219      *
9220      * var users = [
9221      *   { 'user': 'barney',  'age': 36, 'active': true },
9222      *   { 'user': 'fred',    'age': 40, 'active': false },
9223      *   { 'user': 'pebbles', 'age': 1,  'active': true }
9224      * ];
9225      *
9226      * _.find(users, function(o) { return o.age < 40; });
9227      * // => object for 'barney'
9228      *
9229      * // The `_.matches` iteratee shorthand.
9230      * _.find(users, { 'age': 1, 'active': true });
9231      * // => object for 'pebbles'
9232      *
9233      * // The `_.matchesProperty` iteratee shorthand.
9234      * _.find(users, ['active', false]);
9235      * // => object for 'fred'
9236      *
9237      * // The `_.property` iteratee shorthand.
9238      * _.find(users, 'active');
9239      * // => object for 'barney'
9240      */
9241     var find = createFind(findIndex);
9242
9243     /**
9244      * This method is like `_.find` except that it iterates over elements of
9245      * `collection` from right to left.
9246      *
9247      * @static
9248      * @memberOf _
9249      * @since 2.0.0
9250      * @category Collection
9251      * @param {Array|Object} collection The collection to inspect.
9252      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9253      * @param {number} [fromIndex=collection.length-1] The index to search from.
9254      * @returns {*} Returns the matched element, else `undefined`.
9255      * @example
9256      *
9257      * _.findLast([1, 2, 3, 4], function(n) {
9258      *   return n % 2 == 1;
9259      * });
9260      * // => 3
9261      */
9262     var findLast = createFind(findLastIndex);
9263
9264     /**
9265      * Creates a flattened array of values by running each element in `collection`
9266      * thru `iteratee` and flattening the mapped results. The iteratee is invoked
9267      * with three arguments: (value, index|key, collection).
9268      *
9269      * @static
9270      * @memberOf _
9271      * @since 4.0.0
9272      * @category Collection
9273      * @param {Array|Object} collection The collection to iterate over.
9274      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9275      * @returns {Array} Returns the new flattened array.
9276      * @example
9277      *
9278      * function duplicate(n) {
9279      *   return [n, n];
9280      * }
9281      *
9282      * _.flatMap([1, 2], duplicate);
9283      * // => [1, 1, 2, 2]
9284      */
9285     function flatMap(collection, iteratee) {
9286       return baseFlatten(map(collection, iteratee), 1);
9287     }
9288
9289     /**
9290      * This method is like `_.flatMap` except that it recursively flattens the
9291      * mapped results.
9292      *
9293      * @static
9294      * @memberOf _
9295      * @since 4.7.0
9296      * @category Collection
9297      * @param {Array|Object} collection The collection to iterate over.
9298      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9299      * @returns {Array} Returns the new flattened array.
9300      * @example
9301      *
9302      * function duplicate(n) {
9303      *   return [[[n, n]]];
9304      * }
9305      *
9306      * _.flatMapDeep([1, 2], duplicate);
9307      * // => [1, 1, 2, 2]
9308      */
9309     function flatMapDeep(collection, iteratee) {
9310       return baseFlatten(map(collection, iteratee), INFINITY);
9311     }
9312
9313     /**
9314      * This method is like `_.flatMap` except that it recursively flattens the
9315      * mapped results up to `depth` times.
9316      *
9317      * @static
9318      * @memberOf _
9319      * @since 4.7.0
9320      * @category Collection
9321      * @param {Array|Object} collection The collection to iterate over.
9322      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9323      * @param {number} [depth=1] The maximum recursion depth.
9324      * @returns {Array} Returns the new flattened array.
9325      * @example
9326      *
9327      * function duplicate(n) {
9328      *   return [[[n, n]]];
9329      * }
9330      *
9331      * _.flatMapDepth([1, 2], duplicate, 2);
9332      * // => [[1, 1], [2, 2]]
9333      */
9334     function flatMapDepth(collection, iteratee, depth) {
9335       depth = depth === undefined ? 1 : toInteger(depth);
9336       return baseFlatten(map(collection, iteratee), depth);
9337     }
9338
9339     /**
9340      * Iterates over elements of `collection` and invokes `iteratee` for each element.
9341      * The iteratee is invoked with three arguments: (value, index|key, collection).
9342      * Iteratee functions may exit iteration early by explicitly returning `false`.
9343      *
9344      * **Note:** As with other "Collections" methods, objects with a "length"
9345      * property are iterated like arrays. To avoid this behavior use `_.forIn`
9346      * or `_.forOwn` for object iteration.
9347      *
9348      * @static
9349      * @memberOf _
9350      * @since 0.1.0
9351      * @alias each
9352      * @category Collection
9353      * @param {Array|Object} collection The collection to iterate over.
9354      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9355      * @returns {Array|Object} Returns `collection`.
9356      * @see _.forEachRight
9357      * @example
9358      *
9359      * _.forEach([1, 2], function(value) {
9360      *   console.log(value);
9361      * });
9362      * // => Logs `1` then `2`.
9363      *
9364      * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
9365      *   console.log(key);
9366      * });
9367      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
9368      */
9369     function forEach(collection, iteratee) {
9370       var func = isArray(collection) ? arrayEach : baseEach;
9371       return func(collection, getIteratee(iteratee, 3));
9372     }
9373
9374     /**
9375      * This method is like `_.forEach` except that it iterates over elements of
9376      * `collection` from right to left.
9377      *
9378      * @static
9379      * @memberOf _
9380      * @since 2.0.0
9381      * @alias eachRight
9382      * @category Collection
9383      * @param {Array|Object} collection The collection to iterate over.
9384      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9385      * @returns {Array|Object} Returns `collection`.
9386      * @see _.forEach
9387      * @example
9388      *
9389      * _.forEachRight([1, 2], function(value) {
9390      *   console.log(value);
9391      * });
9392      * // => Logs `2` then `1`.
9393      */
9394     function forEachRight(collection, iteratee) {
9395       var func = isArray(collection) ? arrayEachRight : baseEachRight;
9396       return func(collection, getIteratee(iteratee, 3));
9397     }
9398
9399     /**
9400      * Creates an object composed of keys generated from the results of running
9401      * each element of `collection` thru `iteratee`. The order of grouped values
9402      * is determined by the order they occur in `collection`. The corresponding
9403      * value of each key is an array of elements responsible for generating the
9404      * key. The iteratee is invoked with one argument: (value).
9405      *
9406      * @static
9407      * @memberOf _
9408      * @since 0.1.0
9409      * @category Collection
9410      * @param {Array|Object} collection The collection to iterate over.
9411      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9412      * @returns {Object} Returns the composed aggregate object.
9413      * @example
9414      *
9415      * _.groupBy([6.1, 4.2, 6.3], Math.floor);
9416      * // => { '4': [4.2], '6': [6.1, 6.3] }
9417      *
9418      * // The `_.property` iteratee shorthand.
9419      * _.groupBy(['one', 'two', 'three'], 'length');
9420      * // => { '3': ['one', 'two'], '5': ['three'] }
9421      */
9422     var groupBy = createAggregator(function(result, value, key) {
9423       if (hasOwnProperty.call(result, key)) {
9424         result[key].push(value);
9425       } else {
9426         baseAssignValue(result, key, [value]);
9427       }
9428     });
9429
9430     /**
9431      * Checks if `value` is in `collection`. If `collection` is a string, it's
9432      * checked for a substring of `value`, otherwise
9433      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
9434      * is used for equality comparisons. If `fromIndex` is negative, it's used as
9435      * the offset from the end of `collection`.
9436      *
9437      * @static
9438      * @memberOf _
9439      * @since 0.1.0
9440      * @category Collection
9441      * @param {Array|Object|string} collection The collection to inspect.
9442      * @param {*} value The value to search for.
9443      * @param {number} [fromIndex=0] The index to search from.
9444      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9445      * @returns {boolean} Returns `true` if `value` is found, else `false`.
9446      * @example
9447      *
9448      * _.includes([1, 2, 3], 1);
9449      * // => true
9450      *
9451      * _.includes([1, 2, 3], 1, 2);
9452      * // => false
9453      *
9454      * _.includes({ 'a': 1, 'b': 2 }, 1);
9455      * // => true
9456      *
9457      * _.includes('abcd', 'bc');
9458      * // => true
9459      */
9460     function includes(collection, value, fromIndex, guard) {
9461       collection = isArrayLike(collection) ? collection : values(collection);
9462       fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
9463
9464       var length = collection.length;
9465       if (fromIndex < 0) {
9466         fromIndex = nativeMax(length + fromIndex, 0);
9467       }
9468       return isString(collection)
9469         ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
9470         : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
9471     }
9472
9473     /**
9474      * Invokes the method at `path` of each element in `collection`, returning
9475      * an array of the results of each invoked method. Any additional arguments
9476      * are provided to each invoked method. If `path` is a function, it's invoked
9477      * for, and `this` bound to, each element in `collection`.
9478      *
9479      * @static
9480      * @memberOf _
9481      * @since 4.0.0
9482      * @category Collection
9483      * @param {Array|Object} collection The collection to iterate over.
9484      * @param {Array|Function|string} path The path of the method to invoke or
9485      *  the function invoked per iteration.
9486      * @param {...*} [args] The arguments to invoke each method with.
9487      * @returns {Array} Returns the array of results.
9488      * @example
9489      *
9490      * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
9491      * // => [[1, 5, 7], [1, 2, 3]]
9492      *
9493      * _.invokeMap([123, 456], String.prototype.split, '');
9494      * // => [['1', '2', '3'], ['4', '5', '6']]
9495      */
9496     var invokeMap = baseRest(function(collection, path, args) {
9497       var index = -1,
9498           isFunc = typeof path == 'function',
9499           result = isArrayLike(collection) ? Array(collection.length) : [];
9500
9501       baseEach(collection, function(value) {
9502         result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
9503       });
9504       return result;
9505     });
9506
9507     /**
9508      * Creates an object composed of keys generated from the results of running
9509      * each element of `collection` thru `iteratee`. The corresponding value of
9510      * each key is the last element responsible for generating the key. The
9511      * iteratee is invoked with one argument: (value).
9512      *
9513      * @static
9514      * @memberOf _
9515      * @since 4.0.0
9516      * @category Collection
9517      * @param {Array|Object} collection The collection to iterate over.
9518      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9519      * @returns {Object} Returns the composed aggregate object.
9520      * @example
9521      *
9522      * var array = [
9523      *   { 'dir': 'left', 'code': 97 },
9524      *   { 'dir': 'right', 'code': 100 }
9525      * ];
9526      *
9527      * _.keyBy(array, function(o) {
9528      *   return String.fromCharCode(o.code);
9529      * });
9530      * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
9531      *
9532      * _.keyBy(array, 'dir');
9533      * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
9534      */
9535     var keyBy = createAggregator(function(result, value, key) {
9536       baseAssignValue(result, key, value);
9537     });
9538
9539     /**
9540      * Creates an array of values by running each element in `collection` thru
9541      * `iteratee`. The iteratee is invoked with three arguments:
9542      * (value, index|key, collection).
9543      *
9544      * Many lodash methods are guarded to work as iteratees for methods like
9545      * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
9546      *
9547      * The guarded methods are:
9548      * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
9549      * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
9550      * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
9551      * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
9552      *
9553      * @static
9554      * @memberOf _
9555      * @since 0.1.0
9556      * @category Collection
9557      * @param {Array|Object} collection The collection to iterate over.
9558      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9559      * @returns {Array} Returns the new mapped array.
9560      * @example
9561      *
9562      * function square(n) {
9563      *   return n * n;
9564      * }
9565      *
9566      * _.map([4, 8], square);
9567      * // => [16, 64]
9568      *
9569      * _.map({ 'a': 4, 'b': 8 }, square);
9570      * // => [16, 64] (iteration order is not guaranteed)
9571      *
9572      * var users = [
9573      *   { 'user': 'barney' },
9574      *   { 'user': 'fred' }
9575      * ];
9576      *
9577      * // The `_.property` iteratee shorthand.
9578      * _.map(users, 'user');
9579      * // => ['barney', 'fred']
9580      */
9581     function map(collection, iteratee) {
9582       var func = isArray(collection) ? arrayMap : baseMap;
9583       return func(collection, getIteratee(iteratee, 3));
9584     }
9585
9586     /**
9587      * This method is like `_.sortBy` except that it allows specifying the sort
9588      * orders of the iteratees to sort by. If `orders` is unspecified, all values
9589      * are sorted in ascending order. Otherwise, specify an order of "desc" for
9590      * descending or "asc" for ascending sort order of corresponding values.
9591      *
9592      * @static
9593      * @memberOf _
9594      * @since 4.0.0
9595      * @category Collection
9596      * @param {Array|Object} collection The collection to iterate over.
9597      * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
9598      *  The iteratees to sort by.
9599      * @param {string[]} [orders] The sort orders of `iteratees`.
9600      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9601      * @returns {Array} Returns the new sorted array.
9602      * @example
9603      *
9604      * var users = [
9605      *   { 'user': 'fred',   'age': 48 },
9606      *   { 'user': 'barney', 'age': 34 },
9607      *   { 'user': 'fred',   'age': 40 },
9608      *   { 'user': 'barney', 'age': 36 }
9609      * ];
9610      *
9611      * // Sort by `user` in ascending order and by `age` in descending order.
9612      * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
9613      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9614      */
9615     function orderBy(collection, iteratees, orders, guard) {
9616       if (collection == null) {
9617         return [];
9618       }
9619       if (!isArray(iteratees)) {
9620         iteratees = iteratees == null ? [] : [iteratees];
9621       }
9622       orders = guard ? undefined : orders;
9623       if (!isArray(orders)) {
9624         orders = orders == null ? [] : [orders];
9625       }
9626       return baseOrderBy(collection, iteratees, orders);
9627     }
9628
9629     /**
9630      * Creates an array of elements split into two groups, the first of which
9631      * contains elements `predicate` returns truthy for, the second of which
9632      * contains elements `predicate` returns falsey for. The predicate is
9633      * invoked with one argument: (value).
9634      *
9635      * @static
9636      * @memberOf _
9637      * @since 3.0.0
9638      * @category Collection
9639      * @param {Array|Object} collection The collection to iterate over.
9640      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9641      * @returns {Array} Returns the array of grouped elements.
9642      * @example
9643      *
9644      * var users = [
9645      *   { 'user': 'barney',  'age': 36, 'active': false },
9646      *   { 'user': 'fred',    'age': 40, 'active': true },
9647      *   { 'user': 'pebbles', 'age': 1,  'active': false }
9648      * ];
9649      *
9650      * _.partition(users, function(o) { return o.active; });
9651      * // => objects for [['fred'], ['barney', 'pebbles']]
9652      *
9653      * // The `_.matches` iteratee shorthand.
9654      * _.partition(users, { 'age': 1, 'active': false });
9655      * // => objects for [['pebbles'], ['barney', 'fred']]
9656      *
9657      * // The `_.matchesProperty` iteratee shorthand.
9658      * _.partition(users, ['active', false]);
9659      * // => objects for [['barney', 'pebbles'], ['fred']]
9660      *
9661      * // The `_.property` iteratee shorthand.
9662      * _.partition(users, 'active');
9663      * // => objects for [['fred'], ['barney', 'pebbles']]
9664      */
9665     var partition = createAggregator(function(result, value, key) {
9666       result[key ? 0 : 1].push(value);
9667     }, function() { return [[], []]; });
9668
9669     /**
9670      * Reduces `collection` to a value which is the accumulated result of running
9671      * each element in `collection` thru `iteratee`, where each successive
9672      * invocation is supplied the return value of the previous. If `accumulator`
9673      * is not given, the first element of `collection` is used as the initial
9674      * value. The iteratee is invoked with four arguments:
9675      * (accumulator, value, index|key, collection).
9676      *
9677      * Many lodash methods are guarded to work as iteratees for methods like
9678      * `_.reduce`, `_.reduceRight`, and `_.transform`.
9679      *
9680      * The guarded methods are:
9681      * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
9682      * and `sortBy`
9683      *
9684      * @static
9685      * @memberOf _
9686      * @since 0.1.0
9687      * @category Collection
9688      * @param {Array|Object} collection The collection to iterate over.
9689      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9690      * @param {*} [accumulator] The initial value.
9691      * @returns {*} Returns the accumulated value.
9692      * @see _.reduceRight
9693      * @example
9694      *
9695      * _.reduce([1, 2], function(sum, n) {
9696      *   return sum + n;
9697      * }, 0);
9698      * // => 3
9699      *
9700      * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
9701      *   (result[value] || (result[value] = [])).push(key);
9702      *   return result;
9703      * }, {});
9704      * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
9705      */
9706     function reduce(collection, iteratee, accumulator) {
9707       var func = isArray(collection) ? arrayReduce : baseReduce,
9708           initAccum = arguments.length < 3;
9709
9710       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
9711     }
9712
9713     /**
9714      * This method is like `_.reduce` except that it iterates over elements of
9715      * `collection` from right to left.
9716      *
9717      * @static
9718      * @memberOf _
9719      * @since 0.1.0
9720      * @category Collection
9721      * @param {Array|Object} collection The collection to iterate over.
9722      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9723      * @param {*} [accumulator] The initial value.
9724      * @returns {*} Returns the accumulated value.
9725      * @see _.reduce
9726      * @example
9727      *
9728      * var array = [[0, 1], [2, 3], [4, 5]];
9729      *
9730      * _.reduceRight(array, function(flattened, other) {
9731      *   return flattened.concat(other);
9732      * }, []);
9733      * // => [4, 5, 2, 3, 0, 1]
9734      */
9735     function reduceRight(collection, iteratee, accumulator) {
9736       var func = isArray(collection) ? arrayReduceRight : baseReduce,
9737           initAccum = arguments.length < 3;
9738
9739       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
9740     }
9741
9742     /**
9743      * The opposite of `_.filter`; this method returns the elements of `collection`
9744      * that `predicate` does **not** return truthy for.
9745      *
9746      * @static
9747      * @memberOf _
9748      * @since 0.1.0
9749      * @category Collection
9750      * @param {Array|Object} collection The collection to iterate over.
9751      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9752      * @returns {Array} Returns the new filtered array.
9753      * @see _.filter
9754      * @example
9755      *
9756      * var users = [
9757      *   { 'user': 'barney', 'age': 36, 'active': false },
9758      *   { 'user': 'fred',   'age': 40, 'active': true }
9759      * ];
9760      *
9761      * _.reject(users, function(o) { return !o.active; });
9762      * // => objects for ['fred']
9763      *
9764      * // The `_.matches` iteratee shorthand.
9765      * _.reject(users, { 'age': 40, 'active': true });
9766      * // => objects for ['barney']
9767      *
9768      * // The `_.matchesProperty` iteratee shorthand.
9769      * _.reject(users, ['active', false]);
9770      * // => objects for ['fred']
9771      *
9772      * // The `_.property` iteratee shorthand.
9773      * _.reject(users, 'active');
9774      * // => objects for ['barney']
9775      */
9776     function reject(collection, predicate) {
9777       var func = isArray(collection) ? arrayFilter : baseFilter;
9778       return func(collection, negate(getIteratee(predicate, 3)));
9779     }
9780
9781     /**
9782      * Gets a random element from `collection`.
9783      *
9784      * @static
9785      * @memberOf _
9786      * @since 2.0.0
9787      * @category Collection
9788      * @param {Array|Object} collection The collection to sample.
9789      * @returns {*} Returns the random element.
9790      * @example
9791      *
9792      * _.sample([1, 2, 3, 4]);
9793      * // => 2
9794      */
9795     function sample(collection) {
9796       var func = isArray(collection) ? arraySample : baseSample;
9797       return func(collection);
9798     }
9799
9800     /**
9801      * Gets `n` random elements at unique keys from `collection` up to the
9802      * size of `collection`.
9803      *
9804      * @static
9805      * @memberOf _
9806      * @since 4.0.0
9807      * @category Collection
9808      * @param {Array|Object} collection The collection to sample.
9809      * @param {number} [n=1] The number of elements to sample.
9810      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9811      * @returns {Array} Returns the random elements.
9812      * @example
9813      *
9814      * _.sampleSize([1, 2, 3], 2);
9815      * // => [3, 1]
9816      *
9817      * _.sampleSize([1, 2, 3], 4);
9818      * // => [2, 3, 1]
9819      */
9820     function sampleSize(collection, n, guard) {
9821       if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
9822         n = 1;
9823       } else {
9824         n = toInteger(n);
9825       }
9826       var func = isArray(collection) ? arraySampleSize : baseSampleSize;
9827       return func(collection, n);
9828     }
9829
9830     /**
9831      * Creates an array of shuffled values, using a version of the
9832      * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
9833      *
9834      * @static
9835      * @memberOf _
9836      * @since 0.1.0
9837      * @category Collection
9838      * @param {Array|Object} collection The collection to shuffle.
9839      * @returns {Array} Returns the new shuffled array.
9840      * @example
9841      *
9842      * _.shuffle([1, 2, 3, 4]);
9843      * // => [4, 1, 3, 2]
9844      */
9845     function shuffle(collection) {
9846       var func = isArray(collection) ? arrayShuffle : baseShuffle;
9847       return func(collection);
9848     }
9849
9850     /**
9851      * Gets the size of `collection` by returning its length for array-like
9852      * values or the number of own enumerable string keyed properties for objects.
9853      *
9854      * @static
9855      * @memberOf _
9856      * @since 0.1.0
9857      * @category Collection
9858      * @param {Array|Object|string} collection The collection to inspect.
9859      * @returns {number} Returns the collection size.
9860      * @example
9861      *
9862      * _.size([1, 2, 3]);
9863      * // => 3
9864      *
9865      * _.size({ 'a': 1, 'b': 2 });
9866      * // => 2
9867      *
9868      * _.size('pebbles');
9869      * // => 7
9870      */
9871     function size(collection) {
9872       if (collection == null) {
9873         return 0;
9874       }
9875       if (isArrayLike(collection)) {
9876         return isString(collection) ? stringSize(collection) : collection.length;
9877       }
9878       var tag = getTag(collection);
9879       if (tag == mapTag || tag == setTag) {
9880         return collection.size;
9881       }
9882       return baseKeys(collection).length;
9883     }
9884
9885     /**
9886      * Checks if `predicate` returns truthy for **any** element of `collection`.
9887      * Iteration is stopped once `predicate` returns truthy. The predicate is
9888      * invoked with three arguments: (value, index|key, collection).
9889      *
9890      * @static
9891      * @memberOf _
9892      * @since 0.1.0
9893      * @category Collection
9894      * @param {Array|Object} collection The collection to iterate over.
9895      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9896      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9897      * @returns {boolean} Returns `true` if any element passes the predicate check,
9898      *  else `false`.
9899      * @example
9900      *
9901      * _.some([null, 0, 'yes', false], Boolean);
9902      * // => true
9903      *
9904      * var users = [
9905      *   { 'user': 'barney', 'active': true },
9906      *   { 'user': 'fred',   'active': false }
9907      * ];
9908      *
9909      * // The `_.matches` iteratee shorthand.
9910      * _.some(users, { 'user': 'barney', 'active': false });
9911      * // => false
9912      *
9913      * // The `_.matchesProperty` iteratee shorthand.
9914      * _.some(users, ['active', false]);
9915      * // => true
9916      *
9917      * // The `_.property` iteratee shorthand.
9918      * _.some(users, 'active');
9919      * // => true
9920      */
9921     function some(collection, predicate, guard) {
9922       var func = isArray(collection) ? arraySome : baseSome;
9923       if (guard && isIterateeCall(collection, predicate, guard)) {
9924         predicate = undefined;
9925       }
9926       return func(collection, getIteratee(predicate, 3));
9927     }
9928
9929     /**
9930      * Creates an array of elements, sorted in ascending order by the results of
9931      * running each element in a collection thru each iteratee. This method
9932      * performs a stable sort, that is, it preserves the original sort order of
9933      * equal elements. The iteratees are invoked with one argument: (value).
9934      *
9935      * @static
9936      * @memberOf _
9937      * @since 0.1.0
9938      * @category Collection
9939      * @param {Array|Object} collection The collection to iterate over.
9940      * @param {...(Function|Function[])} [iteratees=[_.identity]]
9941      *  The iteratees to sort by.
9942      * @returns {Array} Returns the new sorted array.
9943      * @example
9944      *
9945      * var users = [
9946      *   { 'user': 'fred',   'age': 48 },
9947      *   { 'user': 'barney', 'age': 36 },
9948      *   { 'user': 'fred',   'age': 40 },
9949      *   { 'user': 'barney', 'age': 34 }
9950      * ];
9951      *
9952      * _.sortBy(users, [function(o) { return o.user; }]);
9953      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9954      *
9955      * _.sortBy(users, ['user', 'age']);
9956      * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
9957      */
9958     var sortBy = baseRest(function(collection, iteratees) {
9959       if (collection == null) {
9960         return [];
9961       }
9962       var length = iteratees.length;
9963       if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
9964         iteratees = [];
9965       } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
9966         iteratees = [iteratees[0]];
9967       }
9968       return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
9969     });
9970
9971     /*------------------------------------------------------------------------*/
9972
9973     /**
9974      * Gets the timestamp of the number of milliseconds that have elapsed since
9975      * the Unix epoch (1 January 1970 00:00:00 UTC).
9976      *
9977      * @static
9978      * @memberOf _
9979      * @since 2.4.0
9980      * @category Date
9981      * @returns {number} Returns the timestamp.
9982      * @example
9983      *
9984      * _.defer(function(stamp) {
9985      *   console.log(_.now() - stamp);
9986      * }, _.now());
9987      * // => Logs the number of milliseconds it took for the deferred invocation.
9988      */
9989     var now = ctxNow || function() {
9990       return root.Date.now();
9991     };
9992
9993     /*------------------------------------------------------------------------*/
9994
9995     /**
9996      * The opposite of `_.before`; this method creates a function that invokes
9997      * `func` once it's called `n` or more times.
9998      *
9999      * @static
10000      * @memberOf _
10001      * @since 0.1.0
10002      * @category Function
10003      * @param {number} n The number of calls before `func` is invoked.
10004      * @param {Function} func The function to restrict.
10005      * @returns {Function} Returns the new restricted function.
10006      * @example
10007      *
10008      * var saves = ['profile', 'settings'];
10009      *
10010      * var done = _.after(saves.length, function() {
10011      *   console.log('done saving!');
10012      * });
10013      *
10014      * _.forEach(saves, function(type) {
10015      *   asyncSave({ 'type': type, 'complete': done });
10016      * });
10017      * // => Logs 'done saving!' after the two async saves have completed.
10018      */
10019     function after(n, func) {
10020       if (typeof func != 'function') {
10021         throw new TypeError(FUNC_ERROR_TEXT);
10022       }
10023       n = toInteger(n);
10024       return function() {
10025         if (--n < 1) {
10026           return func.apply(this, arguments);
10027         }
10028       };
10029     }
10030
10031     /**
10032      * Creates a function that invokes `func`, with up to `n` arguments,
10033      * ignoring any additional arguments.
10034      *
10035      * @static
10036      * @memberOf _
10037      * @since 3.0.0
10038      * @category Function
10039      * @param {Function} func The function to cap arguments for.
10040      * @param {number} [n=func.length] The arity cap.
10041      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10042      * @returns {Function} Returns the new capped function.
10043      * @example
10044      *
10045      * _.map(['6', '8', '10'], _.ary(parseInt, 1));
10046      * // => [6, 8, 10]
10047      */
10048     function ary(func, n, guard) {
10049       n = guard ? undefined : n;
10050       n = (func && n == null) ? func.length : n;
10051       return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
10052     }
10053
10054     /**
10055      * Creates a function that invokes `func`, with the `this` binding and arguments
10056      * of the created function, while it's called less than `n` times. Subsequent
10057      * calls to the created function return the result of the last `func` invocation.
10058      *
10059      * @static
10060      * @memberOf _
10061      * @since 3.0.0
10062      * @category Function
10063      * @param {number} n The number of calls at which `func` is no longer invoked.
10064      * @param {Function} func The function to restrict.
10065      * @returns {Function} Returns the new restricted function.
10066      * @example
10067      *
10068      * jQuery(element).on('click', _.before(5, addContactToList));
10069      * // => Allows adding up to 4 contacts to the list.
10070      */
10071     function before(n, func) {
10072       var result;
10073       if (typeof func != 'function') {
10074         throw new TypeError(FUNC_ERROR_TEXT);
10075       }
10076       n = toInteger(n);
10077       return function() {
10078         if (--n > 0) {
10079           result = func.apply(this, arguments);
10080         }
10081         if (n <= 1) {
10082           func = undefined;
10083         }
10084         return result;
10085       };
10086     }
10087
10088     /**
10089      * Creates a function that invokes `func` with the `this` binding of `thisArg`
10090      * and `partials` prepended to the arguments it receives.
10091      *
10092      * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
10093      * may be used as a placeholder for partially applied arguments.
10094      *
10095      * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
10096      * property of bound functions.
10097      *
10098      * @static
10099      * @memberOf _
10100      * @since 0.1.0
10101      * @category Function
10102      * @param {Function} func The function to bind.
10103      * @param {*} thisArg The `this` binding of `func`.
10104      * @param {...*} [partials] The arguments to be partially applied.
10105      * @returns {Function} Returns the new bound function.
10106      * @example
10107      *
10108      * function greet(greeting, punctuation) {
10109      *   return greeting + ' ' + this.user + punctuation;
10110      * }
10111      *
10112      * var object = { 'user': 'fred' };
10113      *
10114      * var bound = _.bind(greet, object, 'hi');
10115      * bound('!');
10116      * // => 'hi fred!'
10117      *
10118      * // Bound with placeholders.
10119      * var bound = _.bind(greet, object, _, '!');
10120      * bound('hi');
10121      * // => 'hi fred!'
10122      */
10123     var bind = baseRest(function(func, thisArg, partials) {
10124       var bitmask = WRAP_BIND_FLAG;
10125       if (partials.length) {
10126         var holders = replaceHolders(partials, getHolder(bind));
10127         bitmask |= WRAP_PARTIAL_FLAG;
10128       }
10129       return createWrap(func, bitmask, thisArg, partials, holders);
10130     });
10131
10132     /**
10133      * Creates a function that invokes the method at `object[key]` with `partials`
10134      * prepended to the arguments it receives.
10135      *
10136      * This method differs from `_.bind` by allowing bound functions to reference
10137      * methods that may be redefined or don't yet exist. See
10138      * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
10139      * for more details.
10140      *
10141      * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
10142      * builds, may be used as a placeholder for partially applied arguments.
10143      *
10144      * @static
10145      * @memberOf _
10146      * @since 0.10.0
10147      * @category Function
10148      * @param {Object} object The object to invoke the method on.
10149      * @param {string} key The key of the method.
10150      * @param {...*} [partials] The arguments to be partially applied.
10151      * @returns {Function} Returns the new bound function.
10152      * @example
10153      *
10154      * var object = {
10155      *   'user': 'fred',
10156      *   'greet': function(greeting, punctuation) {
10157      *     return greeting + ' ' + this.user + punctuation;
10158      *   }
10159      * };
10160      *
10161      * var bound = _.bindKey(object, 'greet', 'hi');
10162      * bound('!');
10163      * // => 'hi fred!'
10164      *
10165      * object.greet = function(greeting, punctuation) {
10166      *   return greeting + 'ya ' + this.user + punctuation;
10167      * };
10168      *
10169      * bound('!');
10170      * // => 'hiya fred!'
10171      *
10172      * // Bound with placeholders.
10173      * var bound = _.bindKey(object, 'greet', _, '!');
10174      * bound('hi');
10175      * // => 'hiya fred!'
10176      */
10177     var bindKey = baseRest(function(object, key, partials) {
10178       var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
10179       if (partials.length) {
10180         var holders = replaceHolders(partials, getHolder(bindKey));
10181         bitmask |= WRAP_PARTIAL_FLAG;
10182       }
10183       return createWrap(key, bitmask, object, partials, holders);
10184     });
10185
10186     /**
10187      * Creates a function that accepts arguments of `func` and either invokes
10188      * `func` returning its result, if at least `arity` number of arguments have
10189      * been provided, or returns a function that accepts the remaining `func`
10190      * arguments, and so on. The arity of `func` may be specified if `func.length`
10191      * is not sufficient.
10192      *
10193      * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
10194      * may be used as a placeholder for provided arguments.
10195      *
10196      * **Note:** This method doesn't set the "length" property of curried functions.
10197      *
10198      * @static
10199      * @memberOf _
10200      * @since 2.0.0
10201      * @category Function
10202      * @param {Function} func The function to curry.
10203      * @param {number} [arity=func.length] The arity of `func`.
10204      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10205      * @returns {Function} Returns the new curried function.
10206      * @example
10207      *
10208      * var abc = function(a, b, c) {
10209      *   return [a, b, c];
10210      * };
10211      *
10212      * var curried = _.curry(abc);
10213      *
10214      * curried(1)(2)(3);
10215      * // => [1, 2, 3]
10216      *
10217      * curried(1, 2)(3);
10218      * // => [1, 2, 3]
10219      *
10220      * curried(1, 2, 3);
10221      * // => [1, 2, 3]
10222      *
10223      * // Curried with placeholders.
10224      * curried(1)(_, 3)(2);
10225      * // => [1, 2, 3]
10226      */
10227     function curry(func, arity, guard) {
10228       arity = guard ? undefined : arity;
10229       var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10230       result.placeholder = curry.placeholder;
10231       return result;
10232     }
10233
10234     /**
10235      * This method is like `_.curry` except that arguments are applied to `func`
10236      * in the manner of `_.partialRight` instead of `_.partial`.
10237      *
10238      * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
10239      * builds, may be used as a placeholder for provided arguments.
10240      *
10241      * **Note:** This method doesn't set the "length" property of curried functions.
10242      *
10243      * @static
10244      * @memberOf _
10245      * @since 3.0.0
10246      * @category Function
10247      * @param {Function} func The function to curry.
10248      * @param {number} [arity=func.length] The arity of `func`.
10249      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10250      * @returns {Function} Returns the new curried function.
10251      * @example
10252      *
10253      * var abc = function(a, b, c) {
10254      *   return [a, b, c];
10255      * };
10256      *
10257      * var curried = _.curryRight(abc);
10258      *
10259      * curried(3)(2)(1);
10260      * // => [1, 2, 3]
10261      *
10262      * curried(2, 3)(1);
10263      * // => [1, 2, 3]
10264      *
10265      * curried(1, 2, 3);
10266      * // => [1, 2, 3]
10267      *
10268      * // Curried with placeholders.
10269      * curried(3)(1, _)(2);
10270      * // => [1, 2, 3]
10271      */
10272     function curryRight(func, arity, guard) {
10273       arity = guard ? undefined : arity;
10274       var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10275       result.placeholder = curryRight.placeholder;
10276       return result;
10277     }
10278
10279     /**
10280      * Creates a debounced function that delays invoking `func` until after `wait`
10281      * milliseconds have elapsed since the last time the debounced function was
10282      * invoked. The debounced function comes with a `cancel` method to cancel
10283      * delayed `func` invocations and a `flush` method to immediately invoke them.
10284      * Provide `options` to indicate whether `func` should be invoked on the
10285      * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
10286      * with the last arguments provided to the debounced function. Subsequent
10287      * calls to the debounced function return the result of the last `func`
10288      * invocation.
10289      *
10290      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10291      * invoked on the trailing edge of the timeout only if the debounced function
10292      * is invoked more than once during the `wait` timeout.
10293      *
10294      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10295      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10296      *
10297      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10298      * for details over the differences between `_.debounce` and `_.throttle`.
10299      *
10300      * @static
10301      * @memberOf _
10302      * @since 0.1.0
10303      * @category Function
10304      * @param {Function} func The function to debounce.
10305      * @param {number} [wait=0] The number of milliseconds to delay.
10306      * @param {Object} [options={}] The options object.
10307      * @param {boolean} [options.leading=false]
10308      *  Specify invoking on the leading edge of the timeout.
10309      * @param {number} [options.maxWait]
10310      *  The maximum time `func` is allowed to be delayed before it's invoked.
10311      * @param {boolean} [options.trailing=true]
10312      *  Specify invoking on the trailing edge of the timeout.
10313      * @returns {Function} Returns the new debounced function.
10314      * @example
10315      *
10316      * // Avoid costly calculations while the window size is in flux.
10317      * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
10318      *
10319      * // Invoke `sendMail` when clicked, debouncing subsequent calls.
10320      * jQuery(element).on('click', _.debounce(sendMail, 300, {
10321      *   'leading': true,
10322      *   'trailing': false
10323      * }));
10324      *
10325      * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
10326      * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
10327      * var source = new EventSource('/stream');
10328      * jQuery(source).on('message', debounced);
10329      *
10330      * // Cancel the trailing debounced invocation.
10331      * jQuery(window).on('popstate', debounced.cancel);
10332      */
10333     function debounce(func, wait, options) {
10334       var lastArgs,
10335           lastThis,
10336           maxWait,
10337           result,
10338           timerId,
10339           lastCallTime,
10340           lastInvokeTime = 0,
10341           leading = false,
10342           maxing = false,
10343           trailing = true;
10344
10345       if (typeof func != 'function') {
10346         throw new TypeError(FUNC_ERROR_TEXT);
10347       }
10348       wait = toNumber(wait) || 0;
10349       if (isObject(options)) {
10350         leading = !!options.leading;
10351         maxing = 'maxWait' in options;
10352         maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
10353         trailing = 'trailing' in options ? !!options.trailing : trailing;
10354       }
10355
10356       function invokeFunc(time) {
10357         var args = lastArgs,
10358             thisArg = lastThis;
10359
10360         lastArgs = lastThis = undefined;
10361         lastInvokeTime = time;
10362         result = func.apply(thisArg, args);
10363         return result;
10364       }
10365
10366       function leadingEdge(time) {
10367         // Reset any `maxWait` timer.
10368         lastInvokeTime = time;
10369         // Start the timer for the trailing edge.
10370         timerId = setTimeout(timerExpired, wait);
10371         // Invoke the leading edge.
10372         return leading ? invokeFunc(time) : result;
10373       }
10374
10375       function remainingWait(time) {
10376         var timeSinceLastCall = time - lastCallTime,
10377             timeSinceLastInvoke = time - lastInvokeTime,
10378             result = wait - timeSinceLastCall;
10379
10380         return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
10381       }
10382
10383       function shouldInvoke(time) {
10384         var timeSinceLastCall = time - lastCallTime,
10385             timeSinceLastInvoke = time - lastInvokeTime;
10386
10387         // Either this is the first call, activity has stopped and we're at the
10388         // trailing edge, the system time has gone backwards and we're treating
10389         // it as the trailing edge, or we've hit the `maxWait` limit.
10390         return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
10391           (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
10392       }
10393
10394       function timerExpired() {
10395         var time = now();
10396         if (shouldInvoke(time)) {
10397           return trailingEdge(time);
10398         }
10399         // Restart the timer.
10400         timerId = setTimeout(timerExpired, remainingWait(time));
10401       }
10402
10403       function trailingEdge(time) {
10404         timerId = undefined;
10405
10406         // Only invoke if we have `lastArgs` which means `func` has been
10407         // debounced at least once.
10408         if (trailing && lastArgs) {
10409           return invokeFunc(time);
10410         }
10411         lastArgs = lastThis = undefined;
10412         return result;
10413       }
10414
10415       function cancel() {
10416         if (timerId !== undefined) {
10417           clearTimeout(timerId);
10418         }
10419         lastInvokeTime = 0;
10420         lastArgs = lastCallTime = lastThis = timerId = undefined;
10421       }
10422
10423       function flush() {
10424         return timerId === undefined ? result : trailingEdge(now());
10425       }
10426
10427       function debounced() {
10428         var time = now(),
10429             isInvoking = shouldInvoke(time);
10430
10431         lastArgs = arguments;
10432         lastThis = this;
10433         lastCallTime = time;
10434
10435         if (isInvoking) {
10436           if (timerId === undefined) {
10437             return leadingEdge(lastCallTime);
10438           }
10439           if (maxing) {
10440             // Handle invocations in a tight loop.
10441             timerId = setTimeout(timerExpired, wait);
10442             return invokeFunc(lastCallTime);
10443           }
10444         }
10445         if (timerId === undefined) {
10446           timerId = setTimeout(timerExpired, wait);
10447         }
10448         return result;
10449       }
10450       debounced.cancel = cancel;
10451       debounced.flush = flush;
10452       return debounced;
10453     }
10454
10455     /**
10456      * Defers invoking the `func` until the current call stack has cleared. Any
10457      * additional arguments are provided to `func` when it's invoked.
10458      *
10459      * @static
10460      * @memberOf _
10461      * @since 0.1.0
10462      * @category Function
10463      * @param {Function} func The function to defer.
10464      * @param {...*} [args] The arguments to invoke `func` with.
10465      * @returns {number} Returns the timer id.
10466      * @example
10467      *
10468      * _.defer(function(text) {
10469      *   console.log(text);
10470      * }, 'deferred');
10471      * // => Logs 'deferred' after one millisecond.
10472      */
10473     var defer = baseRest(function(func, args) {
10474       return baseDelay(func, 1, args);
10475     });
10476
10477     /**
10478      * Invokes `func` after `wait` milliseconds. Any additional arguments are
10479      * provided to `func` when it's invoked.
10480      *
10481      * @static
10482      * @memberOf _
10483      * @since 0.1.0
10484      * @category Function
10485      * @param {Function} func The function to delay.
10486      * @param {number} wait The number of milliseconds to delay invocation.
10487      * @param {...*} [args] The arguments to invoke `func` with.
10488      * @returns {number} Returns the timer id.
10489      * @example
10490      *
10491      * _.delay(function(text) {
10492      *   console.log(text);
10493      * }, 1000, 'later');
10494      * // => Logs 'later' after one second.
10495      */
10496     var delay = baseRest(function(func, wait, args) {
10497       return baseDelay(func, toNumber(wait) || 0, args);
10498     });
10499
10500     /**
10501      * Creates a function that invokes `func` with arguments reversed.
10502      *
10503      * @static
10504      * @memberOf _
10505      * @since 4.0.0
10506      * @category Function
10507      * @param {Function} func The function to flip arguments for.
10508      * @returns {Function} Returns the new flipped function.
10509      * @example
10510      *
10511      * var flipped = _.flip(function() {
10512      *   return _.toArray(arguments);
10513      * });
10514      *
10515      * flipped('a', 'b', 'c', 'd');
10516      * // => ['d', 'c', 'b', 'a']
10517      */
10518     function flip(func) {
10519       return createWrap(func, WRAP_FLIP_FLAG);
10520     }
10521
10522     /**
10523      * Creates a function that memoizes the result of `func`. If `resolver` is
10524      * provided, it determines the cache key for storing the result based on the
10525      * arguments provided to the memoized function. By default, the first argument
10526      * provided to the memoized function is used as the map cache key. The `func`
10527      * is invoked with the `this` binding of the memoized function.
10528      *
10529      * **Note:** The cache is exposed as the `cache` property on the memoized
10530      * function. Its creation may be customized by replacing the `_.memoize.Cache`
10531      * constructor with one whose instances implement the
10532      * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
10533      * method interface of `clear`, `delete`, `get`, `has`, and `set`.
10534      *
10535      * @static
10536      * @memberOf _
10537      * @since 0.1.0
10538      * @category Function
10539      * @param {Function} func The function to have its output memoized.
10540      * @param {Function} [resolver] The function to resolve the cache key.
10541      * @returns {Function} Returns the new memoized function.
10542      * @example
10543      *
10544      * var object = { 'a': 1, 'b': 2 };
10545      * var other = { 'c': 3, 'd': 4 };
10546      *
10547      * var values = _.memoize(_.values);
10548      * values(object);
10549      * // => [1, 2]
10550      *
10551      * values(other);
10552      * // => [3, 4]
10553      *
10554      * object.a = 2;
10555      * values(object);
10556      * // => [1, 2]
10557      *
10558      * // Modify the result cache.
10559      * values.cache.set(object, ['a', 'b']);
10560      * values(object);
10561      * // => ['a', 'b']
10562      *
10563      * // Replace `_.memoize.Cache`.
10564      * _.memoize.Cache = WeakMap;
10565      */
10566     function memoize(func, resolver) {
10567       if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
10568         throw new TypeError(FUNC_ERROR_TEXT);
10569       }
10570       var memoized = function() {
10571         var args = arguments,
10572             key = resolver ? resolver.apply(this, args) : args[0],
10573             cache = memoized.cache;
10574
10575         if (cache.has(key)) {
10576           return cache.get(key);
10577         }
10578         var result = func.apply(this, args);
10579         memoized.cache = cache.set(key, result) || cache;
10580         return result;
10581       };
10582       memoized.cache = new (memoize.Cache || MapCache);
10583       return memoized;
10584     }
10585
10586     // Expose `MapCache`.
10587     memoize.Cache = MapCache;
10588
10589     /**
10590      * Creates a function that negates the result of the predicate `func`. The
10591      * `func` predicate is invoked with the `this` binding and arguments of the
10592      * created function.
10593      *
10594      * @static
10595      * @memberOf _
10596      * @since 3.0.0
10597      * @category Function
10598      * @param {Function} predicate The predicate to negate.
10599      * @returns {Function} Returns the new negated function.
10600      * @example
10601      *
10602      * function isEven(n) {
10603      *   return n % 2 == 0;
10604      * }
10605      *
10606      * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
10607      * // => [1, 3, 5]
10608      */
10609     function negate(predicate) {
10610       if (typeof predicate != 'function') {
10611         throw new TypeError(FUNC_ERROR_TEXT);
10612       }
10613       return function() {
10614         var args = arguments;
10615         switch (args.length) {
10616           case 0: return !predicate.call(this);
10617           case 1: return !predicate.call(this, args[0]);
10618           case 2: return !predicate.call(this, args[0], args[1]);
10619           case 3: return !predicate.call(this, args[0], args[1], args[2]);
10620         }
10621         return !predicate.apply(this, args);
10622       };
10623     }
10624
10625     /**
10626      * Creates a function that is restricted to invoking `func` once. Repeat calls
10627      * to the function return the value of the first invocation. The `func` is
10628      * invoked with the `this` binding and arguments of the created function.
10629      *
10630      * @static
10631      * @memberOf _
10632      * @since 0.1.0
10633      * @category Function
10634      * @param {Function} func The function to restrict.
10635      * @returns {Function} Returns the new restricted function.
10636      * @example
10637      *
10638      * var initialize = _.once(createApplication);
10639      * initialize();
10640      * initialize();
10641      * // => `createApplication` is invoked once
10642      */
10643     function once(func) {
10644       return before(2, func);
10645     }
10646
10647     /**
10648      * Creates a function that invokes `func` with its arguments transformed.
10649      *
10650      * @static
10651      * @since 4.0.0
10652      * @memberOf _
10653      * @category Function
10654      * @param {Function} func The function to wrap.
10655      * @param {...(Function|Function[])} [transforms=[_.identity]]
10656      *  The argument transforms.
10657      * @returns {Function} Returns the new function.
10658      * @example
10659      *
10660      * function doubled(n) {
10661      *   return n * 2;
10662      * }
10663      *
10664      * function square(n) {
10665      *   return n * n;
10666      * }
10667      *
10668      * var func = _.overArgs(function(x, y) {
10669      *   return [x, y];
10670      * }, [square, doubled]);
10671      *
10672      * func(9, 3);
10673      * // => [81, 6]
10674      *
10675      * func(10, 5);
10676      * // => [100, 10]
10677      */
10678     var overArgs = castRest(function(func, transforms) {
10679       transforms = (transforms.length == 1 && isArray(transforms[0]))
10680         ? arrayMap(transforms[0], baseUnary(getIteratee()))
10681         : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
10682
10683       var funcsLength = transforms.length;
10684       return baseRest(function(args) {
10685         var index = -1,
10686             length = nativeMin(args.length, funcsLength);
10687
10688         while (++index < length) {
10689           args[index] = transforms[index].call(this, args[index]);
10690         }
10691         return apply(func, this, args);
10692       });
10693     });
10694
10695     /**
10696      * Creates a function that invokes `func` with `partials` prepended to the
10697      * arguments it receives. This method is like `_.bind` except it does **not**
10698      * alter the `this` binding.
10699      *
10700      * The `_.partial.placeholder` value, which defaults to `_` in monolithic
10701      * builds, may be used as a placeholder for partially applied arguments.
10702      *
10703      * **Note:** This method doesn't set the "length" property of partially
10704      * applied functions.
10705      *
10706      * @static
10707      * @memberOf _
10708      * @since 0.2.0
10709      * @category Function
10710      * @param {Function} func The function to partially apply arguments to.
10711      * @param {...*} [partials] The arguments to be partially applied.
10712      * @returns {Function} Returns the new partially applied function.
10713      * @example
10714      *
10715      * function greet(greeting, name) {
10716      *   return greeting + ' ' + name;
10717      * }
10718      *
10719      * var sayHelloTo = _.partial(greet, 'hello');
10720      * sayHelloTo('fred');
10721      * // => 'hello fred'
10722      *
10723      * // Partially applied with placeholders.
10724      * var greetFred = _.partial(greet, _, 'fred');
10725      * greetFred('hi');
10726      * // => 'hi fred'
10727      */
10728     var partial = baseRest(function(func, partials) {
10729       var holders = replaceHolders(partials, getHolder(partial));
10730       return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
10731     });
10732
10733     /**
10734      * This method is like `_.partial` except that partially applied arguments
10735      * are appended to the arguments it receives.
10736      *
10737      * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
10738      * builds, may be used as a placeholder for partially applied arguments.
10739      *
10740      * **Note:** This method doesn't set the "length" property of partially
10741      * applied functions.
10742      *
10743      * @static
10744      * @memberOf _
10745      * @since 1.0.0
10746      * @category Function
10747      * @param {Function} func The function to partially apply arguments to.
10748      * @param {...*} [partials] The arguments to be partially applied.
10749      * @returns {Function} Returns the new partially applied function.
10750      * @example
10751      *
10752      * function greet(greeting, name) {
10753      *   return greeting + ' ' + name;
10754      * }
10755      *
10756      * var greetFred = _.partialRight(greet, 'fred');
10757      * greetFred('hi');
10758      * // => 'hi fred'
10759      *
10760      * // Partially applied with placeholders.
10761      * var sayHelloTo = _.partialRight(greet, 'hello', _);
10762      * sayHelloTo('fred');
10763      * // => 'hello fred'
10764      */
10765     var partialRight = baseRest(function(func, partials) {
10766       var holders = replaceHolders(partials, getHolder(partialRight));
10767       return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
10768     });
10769
10770     /**
10771      * Creates a function that invokes `func` with arguments arranged according
10772      * to the specified `indexes` where the argument value at the first index is
10773      * provided as the first argument, the argument value at the second index is
10774      * provided as the second argument, and so on.
10775      *
10776      * @static
10777      * @memberOf _
10778      * @since 3.0.0
10779      * @category Function
10780      * @param {Function} func The function to rearrange arguments for.
10781      * @param {...(number|number[])} indexes The arranged argument indexes.
10782      * @returns {Function} Returns the new function.
10783      * @example
10784      *
10785      * var rearged = _.rearg(function(a, b, c) {
10786      *   return [a, b, c];
10787      * }, [2, 0, 1]);
10788      *
10789      * rearged('b', 'c', 'a')
10790      * // => ['a', 'b', 'c']
10791      */
10792     var rearg = flatRest(function(func, indexes) {
10793       return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
10794     });
10795
10796     /**
10797      * Creates a function that invokes `func` with the `this` binding of the
10798      * created function and arguments from `start` and beyond provided as
10799      * an array.
10800      *
10801      * **Note:** This method is based on the
10802      * [rest parameter](https://mdn.io/rest_parameters).
10803      *
10804      * @static
10805      * @memberOf _
10806      * @since 4.0.0
10807      * @category Function
10808      * @param {Function} func The function to apply a rest parameter to.
10809      * @param {number} [start=func.length-1] The start position of the rest parameter.
10810      * @returns {Function} Returns the new function.
10811      * @example
10812      *
10813      * var say = _.rest(function(what, names) {
10814      *   return what + ' ' + _.initial(names).join(', ') +
10815      *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
10816      * });
10817      *
10818      * say('hello', 'fred', 'barney', 'pebbles');
10819      * // => 'hello fred, barney, & pebbles'
10820      */
10821     function rest(func, start) {
10822       if (typeof func != 'function') {
10823         throw new TypeError(FUNC_ERROR_TEXT);
10824       }
10825       start = start === undefined ? start : toInteger(start);
10826       return baseRest(func, start);
10827     }
10828
10829     /**
10830      * Creates a function that invokes `func` with the `this` binding of the
10831      * create function and an array of arguments much like
10832      * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
10833      *
10834      * **Note:** This method is based on the
10835      * [spread operator](https://mdn.io/spread_operator).
10836      *
10837      * @static
10838      * @memberOf _
10839      * @since 3.2.0
10840      * @category Function
10841      * @param {Function} func The function to spread arguments over.
10842      * @param {number} [start=0] The start position of the spread.
10843      * @returns {Function} Returns the new function.
10844      * @example
10845      *
10846      * var say = _.spread(function(who, what) {
10847      *   return who + ' says ' + what;
10848      * });
10849      *
10850      * say(['fred', 'hello']);
10851      * // => 'fred says hello'
10852      *
10853      * var numbers = Promise.all([
10854      *   Promise.resolve(40),
10855      *   Promise.resolve(36)
10856      * ]);
10857      *
10858      * numbers.then(_.spread(function(x, y) {
10859      *   return x + y;
10860      * }));
10861      * // => a Promise of 76
10862      */
10863     function spread(func, start) {
10864       if (typeof func != 'function') {
10865         throw new TypeError(FUNC_ERROR_TEXT);
10866       }
10867       start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
10868       return baseRest(function(args) {
10869         var array = args[start],
10870             lastIndex = args.length - 1,
10871             otherArgs = castSlice(args, 0, start);
10872
10873         if (array) {
10874           arrayPush(otherArgs, array);
10875         }
10876         if (start != lastIndex) {
10877           arrayPush(otherArgs, castSlice(args, start + 1));
10878         }
10879         return apply(func, this, otherArgs);
10880       });
10881     }
10882
10883     /**
10884      * Creates a throttled function that only invokes `func` at most once per
10885      * every `wait` milliseconds. The throttled function comes with a `cancel`
10886      * method to cancel delayed `func` invocations and a `flush` method to
10887      * immediately invoke them. Provide `options` to indicate whether `func`
10888      * should be invoked on the leading and/or trailing edge of the `wait`
10889      * timeout. The `func` is invoked with the last arguments provided to the
10890      * throttled function. Subsequent calls to the throttled function return the
10891      * result of the last `func` invocation.
10892      *
10893      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10894      * invoked on the trailing edge of the timeout only if the throttled function
10895      * is invoked more than once during the `wait` timeout.
10896      *
10897      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10898      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10899      *
10900      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10901      * for details over the differences between `_.throttle` and `_.debounce`.
10902      *
10903      * @static
10904      * @memberOf _
10905      * @since 0.1.0
10906      * @category Function
10907      * @param {Function} func The function to throttle.
10908      * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
10909      * @param {Object} [options={}] The options object.
10910      * @param {boolean} [options.leading=true]
10911      *  Specify invoking on the leading edge of the timeout.
10912      * @param {boolean} [options.trailing=true]
10913      *  Specify invoking on the trailing edge of the timeout.
10914      * @returns {Function} Returns the new throttled function.
10915      * @example
10916      *
10917      * // Avoid excessively updating the position while scrolling.
10918      * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
10919      *
10920      * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
10921      * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
10922      * jQuery(element).on('click', throttled);
10923      *
10924      * // Cancel the trailing throttled invocation.
10925      * jQuery(window).on('popstate', throttled.cancel);
10926      */
10927     function throttle(func, wait, options) {
10928       var leading = true,
10929           trailing = true;
10930
10931       if (typeof func != 'function') {
10932         throw new TypeError(FUNC_ERROR_TEXT);
10933       }
10934       if (isObject(options)) {
10935         leading = 'leading' in options ? !!options.leading : leading;
10936         trailing = 'trailing' in options ? !!options.trailing : trailing;
10937       }
10938       return debounce(func, wait, {
10939         'leading': leading,
10940         'maxWait': wait,
10941         'trailing': trailing
10942       });
10943     }
10944
10945     /**
10946      * Creates a function that accepts up to one argument, ignoring any
10947      * additional arguments.
10948      *
10949      * @static
10950      * @memberOf _
10951      * @since 4.0.0
10952      * @category Function
10953      * @param {Function} func The function to cap arguments for.
10954      * @returns {Function} Returns the new capped function.
10955      * @example
10956      *
10957      * _.map(['6', '8', '10'], _.unary(parseInt));
10958      * // => [6, 8, 10]
10959      */
10960     function unary(func) {
10961       return ary(func, 1);
10962     }
10963
10964     /**
10965      * Creates a function that provides `value` to `wrapper` as its first
10966      * argument. Any additional arguments provided to the function are appended
10967      * to those provided to the `wrapper`. The wrapper is invoked with the `this`
10968      * binding of the created function.
10969      *
10970      * @static
10971      * @memberOf _
10972      * @since 0.1.0
10973      * @category Function
10974      * @param {*} value The value to wrap.
10975      * @param {Function} [wrapper=identity] The wrapper function.
10976      * @returns {Function} Returns the new function.
10977      * @example
10978      *
10979      * var p = _.wrap(_.escape, function(func, text) {
10980      *   return '<p>' + func(text) + '</p>';
10981      * });
10982      *
10983      * p('fred, barney, & pebbles');
10984      * // => '<p>fred, barney, &amp; pebbles</p>'
10985      */
10986     function wrap(value, wrapper) {
10987       return partial(castFunction(wrapper), value);
10988     }
10989
10990     /*------------------------------------------------------------------------*/
10991
10992     /**
10993      * Casts `value` as an array if it's not one.
10994      *
10995      * @static
10996      * @memberOf _
10997      * @since 4.4.0
10998      * @category Lang
10999      * @param {*} value The value to inspect.
11000      * @returns {Array} Returns the cast array.
11001      * @example
11002      *
11003      * _.castArray(1);
11004      * // => [1]
11005      *
11006      * _.castArray({ 'a': 1 });
11007      * // => [{ 'a': 1 }]
11008      *
11009      * _.castArray('abc');
11010      * // => ['abc']
11011      *
11012      * _.castArray(null);
11013      * // => [null]
11014      *
11015      * _.castArray(undefined);
11016      * // => [undefined]
11017      *
11018      * _.castArray();
11019      * // => []
11020      *
11021      * var array = [1, 2, 3];
11022      * console.log(_.castArray(array) === array);
11023      * // => true
11024      */
11025     function castArray() {
11026       if (!arguments.length) {
11027         return [];
11028       }
11029       var value = arguments[0];
11030       return isArray(value) ? value : [value];
11031     }
11032
11033     /**
11034      * Creates a shallow clone of `value`.
11035      *
11036      * **Note:** This method is loosely based on the
11037      * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
11038      * and supports cloning arrays, array buffers, booleans, date objects, maps,
11039      * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
11040      * arrays. The own enumerable properties of `arguments` objects are cloned
11041      * as plain objects. An empty object is returned for uncloneable values such
11042      * as error objects, functions, DOM nodes, and WeakMaps.
11043      *
11044      * @static
11045      * @memberOf _
11046      * @since 0.1.0
11047      * @category Lang
11048      * @param {*} value The value to clone.
11049      * @returns {*} Returns the cloned value.
11050      * @see _.cloneDeep
11051      * @example
11052      *
11053      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11054      *
11055      * var shallow = _.clone(objects);
11056      * console.log(shallow[0] === objects[0]);
11057      * // => true
11058      */
11059     function clone(value) {
11060       return baseClone(value, CLONE_SYMBOLS_FLAG);
11061     }
11062
11063     /**
11064      * This method is like `_.clone` except that it accepts `customizer` which
11065      * is invoked to produce the cloned value. If `customizer` returns `undefined`,
11066      * cloning is handled by the method instead. The `customizer` is invoked with
11067      * up to four arguments; (value [, index|key, object, stack]).
11068      *
11069      * @static
11070      * @memberOf _
11071      * @since 4.0.0
11072      * @category Lang
11073      * @param {*} value The value to clone.
11074      * @param {Function} [customizer] The function to customize cloning.
11075      * @returns {*} Returns the cloned value.
11076      * @see _.cloneDeepWith
11077      * @example
11078      *
11079      * function customizer(value) {
11080      *   if (_.isElement(value)) {
11081      *     return value.cloneNode(false);
11082      *   }
11083      * }
11084      *
11085      * var el = _.cloneWith(document.body, customizer);
11086      *
11087      * console.log(el === document.body);
11088      * // => false
11089      * console.log(el.nodeName);
11090      * // => 'BODY'
11091      * console.log(el.childNodes.length);
11092      * // => 0
11093      */
11094     function cloneWith(value, customizer) {
11095       customizer = typeof customizer == 'function' ? customizer : undefined;
11096       return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
11097     }
11098
11099     /**
11100      * This method is like `_.clone` except that it recursively clones `value`.
11101      *
11102      * @static
11103      * @memberOf _
11104      * @since 1.0.0
11105      * @category Lang
11106      * @param {*} value The value to recursively clone.
11107      * @returns {*} Returns the deep cloned value.
11108      * @see _.clone
11109      * @example
11110      *
11111      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11112      *
11113      * var deep = _.cloneDeep(objects);
11114      * console.log(deep[0] === objects[0]);
11115      * // => false
11116      */
11117     function cloneDeep(value) {
11118       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
11119     }
11120
11121     /**
11122      * This method is like `_.cloneWith` except that it recursively clones `value`.
11123      *
11124      * @static
11125      * @memberOf _
11126      * @since 4.0.0
11127      * @category Lang
11128      * @param {*} value The value to recursively clone.
11129      * @param {Function} [customizer] The function to customize cloning.
11130      * @returns {*} Returns the deep cloned value.
11131      * @see _.cloneWith
11132      * @example
11133      *
11134      * function customizer(value) {
11135      *   if (_.isElement(value)) {
11136      *     return value.cloneNode(true);
11137      *   }
11138      * }
11139      *
11140      * var el = _.cloneDeepWith(document.body, customizer);
11141      *
11142      * console.log(el === document.body);
11143      * // => false
11144      * console.log(el.nodeName);
11145      * // => 'BODY'
11146      * console.log(el.childNodes.length);
11147      * // => 20
11148      */
11149     function cloneDeepWith(value, customizer) {
11150       customizer = typeof customizer == 'function' ? customizer : undefined;
11151       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
11152     }
11153
11154     /**
11155      * Checks if `object` conforms to `source` by invoking the predicate
11156      * properties of `source` with the corresponding property values of `object`.
11157      *
11158      * **Note:** This method is equivalent to `_.conforms` when `source` is
11159      * partially applied.
11160      *
11161      * @static
11162      * @memberOf _
11163      * @since 4.14.0
11164      * @category Lang
11165      * @param {Object} object The object to inspect.
11166      * @param {Object} source The object of property predicates to conform to.
11167      * @returns {boolean} Returns `true` if `object` conforms, else `false`.
11168      * @example
11169      *
11170      * var object = { 'a': 1, 'b': 2 };
11171      *
11172      * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
11173      * // => true
11174      *
11175      * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
11176      * // => false
11177      */
11178     function conformsTo(object, source) {
11179       return source == null || baseConformsTo(object, source, keys(source));
11180     }
11181
11182     /**
11183      * Performs a
11184      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
11185      * comparison between two values to determine if they are equivalent.
11186      *
11187      * @static
11188      * @memberOf _
11189      * @since 4.0.0
11190      * @category Lang
11191      * @param {*} value The value to compare.
11192      * @param {*} other The other value to compare.
11193      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11194      * @example
11195      *
11196      * var object = { 'a': 1 };
11197      * var other = { 'a': 1 };
11198      *
11199      * _.eq(object, object);
11200      * // => true
11201      *
11202      * _.eq(object, other);
11203      * // => false
11204      *
11205      * _.eq('a', 'a');
11206      * // => true
11207      *
11208      * _.eq('a', Object('a'));
11209      * // => false
11210      *
11211      * _.eq(NaN, NaN);
11212      * // => true
11213      */
11214     function eq(value, other) {
11215       return value === other || (value !== value && other !== other);
11216     }
11217
11218     /**
11219      * Checks if `value` is greater than `other`.
11220      *
11221      * @static
11222      * @memberOf _
11223      * @since 3.9.0
11224      * @category Lang
11225      * @param {*} value The value to compare.
11226      * @param {*} other The other value to compare.
11227      * @returns {boolean} Returns `true` if `value` is greater than `other`,
11228      *  else `false`.
11229      * @see _.lt
11230      * @example
11231      *
11232      * _.gt(3, 1);
11233      * // => true
11234      *
11235      * _.gt(3, 3);
11236      * // => false
11237      *
11238      * _.gt(1, 3);
11239      * // => false
11240      */
11241     var gt = createRelationalOperation(baseGt);
11242
11243     /**
11244      * Checks if `value` is greater than or equal to `other`.
11245      *
11246      * @static
11247      * @memberOf _
11248      * @since 3.9.0
11249      * @category Lang
11250      * @param {*} value The value to compare.
11251      * @param {*} other The other value to compare.
11252      * @returns {boolean} Returns `true` if `value` is greater than or equal to
11253      *  `other`, else `false`.
11254      * @see _.lte
11255      * @example
11256      *
11257      * _.gte(3, 1);
11258      * // => true
11259      *
11260      * _.gte(3, 3);
11261      * // => true
11262      *
11263      * _.gte(1, 3);
11264      * // => false
11265      */
11266     var gte = createRelationalOperation(function(value, other) {
11267       return value >= other;
11268     });
11269
11270     /**
11271      * Checks if `value` is likely an `arguments` object.
11272      *
11273      * @static
11274      * @memberOf _
11275      * @since 0.1.0
11276      * @category Lang
11277      * @param {*} value The value to check.
11278      * @returns {boolean} Returns `true` if `value` is an `arguments` object,
11279      *  else `false`.
11280      * @example
11281      *
11282      * _.isArguments(function() { return arguments; }());
11283      * // => true
11284      *
11285      * _.isArguments([1, 2, 3]);
11286      * // => false
11287      */
11288     var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
11289       return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
11290         !propertyIsEnumerable.call(value, 'callee');
11291     };
11292
11293     /**
11294      * Checks if `value` is classified as an `Array` object.
11295      *
11296      * @static
11297      * @memberOf _
11298      * @since 0.1.0
11299      * @category Lang
11300      * @param {*} value The value to check.
11301      * @returns {boolean} Returns `true` if `value` is an array, else `false`.
11302      * @example
11303      *
11304      * _.isArray([1, 2, 3]);
11305      * // => true
11306      *
11307      * _.isArray(document.body.children);
11308      * // => false
11309      *
11310      * _.isArray('abc');
11311      * // => false
11312      *
11313      * _.isArray(_.noop);
11314      * // => false
11315      */
11316     var isArray = Array.isArray;
11317
11318     /**
11319      * Checks if `value` is classified as an `ArrayBuffer` object.
11320      *
11321      * @static
11322      * @memberOf _
11323      * @since 4.3.0
11324      * @category Lang
11325      * @param {*} value The value to check.
11326      * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
11327      * @example
11328      *
11329      * _.isArrayBuffer(new ArrayBuffer(2));
11330      * // => true
11331      *
11332      * _.isArrayBuffer(new Array(2));
11333      * // => false
11334      */
11335     var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
11336
11337     /**
11338      * Checks if `value` is array-like. A value is considered array-like if it's
11339      * not a function and has a `value.length` that's an integer greater than or
11340      * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
11341      *
11342      * @static
11343      * @memberOf _
11344      * @since 4.0.0
11345      * @category Lang
11346      * @param {*} value The value to check.
11347      * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
11348      * @example
11349      *
11350      * _.isArrayLike([1, 2, 3]);
11351      * // => true
11352      *
11353      * _.isArrayLike(document.body.children);
11354      * // => true
11355      *
11356      * _.isArrayLike('abc');
11357      * // => true
11358      *
11359      * _.isArrayLike(_.noop);
11360      * // => false
11361      */
11362     function isArrayLike(value) {
11363       return value != null && isLength(value.length) && !isFunction(value);
11364     }
11365
11366     /**
11367      * This method is like `_.isArrayLike` except that it also checks if `value`
11368      * is an object.
11369      *
11370      * @static
11371      * @memberOf _
11372      * @since 4.0.0
11373      * @category Lang
11374      * @param {*} value The value to check.
11375      * @returns {boolean} Returns `true` if `value` is an array-like object,
11376      *  else `false`.
11377      * @example
11378      *
11379      * _.isArrayLikeObject([1, 2, 3]);
11380      * // => true
11381      *
11382      * _.isArrayLikeObject(document.body.children);
11383      * // => true
11384      *
11385      * _.isArrayLikeObject('abc');
11386      * // => false
11387      *
11388      * _.isArrayLikeObject(_.noop);
11389      * // => false
11390      */
11391     function isArrayLikeObject(value) {
11392       return isObjectLike(value) && isArrayLike(value);
11393     }
11394
11395     /**
11396      * Checks if `value` is classified as a boolean primitive or object.
11397      *
11398      * @static
11399      * @memberOf _
11400      * @since 0.1.0
11401      * @category Lang
11402      * @param {*} value The value to check.
11403      * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
11404      * @example
11405      *
11406      * _.isBoolean(false);
11407      * // => true
11408      *
11409      * _.isBoolean(null);
11410      * // => false
11411      */
11412     function isBoolean(value) {
11413       return value === true || value === false ||
11414         (isObjectLike(value) && baseGetTag(value) == boolTag);
11415     }
11416
11417     /**
11418      * Checks if `value` is a buffer.
11419      *
11420      * @static
11421      * @memberOf _
11422      * @since 4.3.0
11423      * @category Lang
11424      * @param {*} value The value to check.
11425      * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
11426      * @example
11427      *
11428      * _.isBuffer(new Buffer(2));
11429      * // => true
11430      *
11431      * _.isBuffer(new Uint8Array(2));
11432      * // => false
11433      */
11434     var isBuffer = nativeIsBuffer || stubFalse;
11435
11436     /**
11437      * Checks if `value` is classified as a `Date` object.
11438      *
11439      * @static
11440      * @memberOf _
11441      * @since 0.1.0
11442      * @category Lang
11443      * @param {*} value The value to check.
11444      * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
11445      * @example
11446      *
11447      * _.isDate(new Date);
11448      * // => true
11449      *
11450      * _.isDate('Mon April 23 2012');
11451      * // => false
11452      */
11453     var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
11454
11455     /**
11456      * Checks if `value` is likely a DOM element.
11457      *
11458      * @static
11459      * @memberOf _
11460      * @since 0.1.0
11461      * @category Lang
11462      * @param {*} value The value to check.
11463      * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
11464      * @example
11465      *
11466      * _.isElement(document.body);
11467      * // => true
11468      *
11469      * _.isElement('<body>');
11470      * // => false
11471      */
11472     function isElement(value) {
11473       return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
11474     }
11475
11476     /**
11477      * Checks if `value` is an empty object, collection, map, or set.
11478      *
11479      * Objects are considered empty if they have no own enumerable string keyed
11480      * properties.
11481      *
11482      * Array-like values such as `arguments` objects, arrays, buffers, strings, or
11483      * jQuery-like collections are considered empty if they have a `length` of `0`.
11484      * Similarly, maps and sets are considered empty if they have a `size` of `0`.
11485      *
11486      * @static
11487      * @memberOf _
11488      * @since 0.1.0
11489      * @category Lang
11490      * @param {*} value The value to check.
11491      * @returns {boolean} Returns `true` if `value` is empty, else `false`.
11492      * @example
11493      *
11494      * _.isEmpty(null);
11495      * // => true
11496      *
11497      * _.isEmpty(true);
11498      * // => true
11499      *
11500      * _.isEmpty(1);
11501      * // => true
11502      *
11503      * _.isEmpty([1, 2, 3]);
11504      * // => false
11505      *
11506      * _.isEmpty({ 'a': 1 });
11507      * // => false
11508      */
11509     function isEmpty(value) {
11510       if (value == null) {
11511         return true;
11512       }
11513       if (isArrayLike(value) &&
11514           (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
11515             isBuffer(value) || isTypedArray(value) || isArguments(value))) {
11516         return !value.length;
11517       }
11518       var tag = getTag(value);
11519       if (tag == mapTag || tag == setTag) {
11520         return !value.size;
11521       }
11522       if (isPrototype(value)) {
11523         return !baseKeys(value).length;
11524       }
11525       for (var key in value) {
11526         if (hasOwnProperty.call(value, key)) {
11527           return false;
11528         }
11529       }
11530       return true;
11531     }
11532
11533     /**
11534      * Performs a deep comparison between two values to determine if they are
11535      * equivalent.
11536      *
11537      * **Note:** This method supports comparing arrays, array buffers, booleans,
11538      * date objects, error objects, maps, numbers, `Object` objects, regexes,
11539      * sets, strings, symbols, and typed arrays. `Object` objects are compared
11540      * by their own, not inherited, enumerable properties. Functions and DOM
11541      * nodes are **not** supported.
11542      *
11543      * @static
11544      * @memberOf _
11545      * @since 0.1.0
11546      * @category Lang
11547      * @param {*} value The value to compare.
11548      * @param {*} other The other value to compare.
11549      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11550      * @example
11551      *
11552      * var object = { 'a': 1 };
11553      * var other = { 'a': 1 };
11554      *
11555      * _.isEqual(object, other);
11556      * // => true
11557      *
11558      * object === other;
11559      * // => false
11560      */
11561     function isEqual(value, other) {
11562       return baseIsEqual(value, other);
11563     }
11564
11565     /**
11566      * This method is like `_.isEqual` except that it accepts `customizer` which
11567      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11568      * are handled by the method instead. The `customizer` is invoked with up to
11569      * six arguments: (objValue, othValue [, index|key, object, other, stack]).
11570      *
11571      * @static
11572      * @memberOf _
11573      * @since 4.0.0
11574      * @category Lang
11575      * @param {*} value The value to compare.
11576      * @param {*} other The other value to compare.
11577      * @param {Function} [customizer] The function to customize comparisons.
11578      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11579      * @example
11580      *
11581      * function isGreeting(value) {
11582      *   return /^h(?:i|ello)$/.test(value);
11583      * }
11584      *
11585      * function customizer(objValue, othValue) {
11586      *   if (isGreeting(objValue) && isGreeting(othValue)) {
11587      *     return true;
11588      *   }
11589      * }
11590      *
11591      * var array = ['hello', 'goodbye'];
11592      * var other = ['hi', 'goodbye'];
11593      *
11594      * _.isEqualWith(array, other, customizer);
11595      * // => true
11596      */
11597     function isEqualWith(value, other, customizer) {
11598       customizer = typeof customizer == 'function' ? customizer : undefined;
11599       var result = customizer ? customizer(value, other) : undefined;
11600       return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
11601     }
11602
11603     /**
11604      * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
11605      * `SyntaxError`, `TypeError`, or `URIError` object.
11606      *
11607      * @static
11608      * @memberOf _
11609      * @since 3.0.0
11610      * @category Lang
11611      * @param {*} value The value to check.
11612      * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
11613      * @example
11614      *
11615      * _.isError(new Error);
11616      * // => true
11617      *
11618      * _.isError(Error);
11619      * // => false
11620      */
11621     function isError(value) {
11622       if (!isObjectLike(value)) {
11623         return false;
11624       }
11625       var tag = baseGetTag(value);
11626       return tag == errorTag || tag == domExcTag ||
11627         (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
11628     }
11629
11630     /**
11631      * Checks if `value` is a finite primitive number.
11632      *
11633      * **Note:** This method is based on
11634      * [`Number.isFinite`](https://mdn.io/Number/isFinite).
11635      *
11636      * @static
11637      * @memberOf _
11638      * @since 0.1.0
11639      * @category Lang
11640      * @param {*} value The value to check.
11641      * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
11642      * @example
11643      *
11644      * _.isFinite(3);
11645      * // => true
11646      *
11647      * _.isFinite(Number.MIN_VALUE);
11648      * // => true
11649      *
11650      * _.isFinite(Infinity);
11651      * // => false
11652      *
11653      * _.isFinite('3');
11654      * // => false
11655      */
11656     function isFinite(value) {
11657       return typeof value == 'number' && nativeIsFinite(value);
11658     }
11659
11660     /**
11661      * Checks if `value` is classified as a `Function` object.
11662      *
11663      * @static
11664      * @memberOf _
11665      * @since 0.1.0
11666      * @category Lang
11667      * @param {*} value The value to check.
11668      * @returns {boolean} Returns `true` if `value` is a function, else `false`.
11669      * @example
11670      *
11671      * _.isFunction(_);
11672      * // => true
11673      *
11674      * _.isFunction(/abc/);
11675      * // => false
11676      */
11677     function isFunction(value) {
11678       if (!isObject(value)) {
11679         return false;
11680       }
11681       // The use of `Object#toString` avoids issues with the `typeof` operator
11682       // in Safari 9 which returns 'object' for typed arrays and other constructors.
11683       var tag = baseGetTag(value);
11684       return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
11685     }
11686
11687     /**
11688      * Checks if `value` is an integer.
11689      *
11690      * **Note:** This method is based on
11691      * [`Number.isInteger`](https://mdn.io/Number/isInteger).
11692      *
11693      * @static
11694      * @memberOf _
11695      * @since 4.0.0
11696      * @category Lang
11697      * @param {*} value The value to check.
11698      * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
11699      * @example
11700      *
11701      * _.isInteger(3);
11702      * // => true
11703      *
11704      * _.isInteger(Number.MIN_VALUE);
11705      * // => false
11706      *
11707      * _.isInteger(Infinity);
11708      * // => false
11709      *
11710      * _.isInteger('3');
11711      * // => false
11712      */
11713     function isInteger(value) {
11714       return typeof value == 'number' && value == toInteger(value);
11715     }
11716
11717     /**
11718      * Checks if `value` is a valid array-like length.
11719      *
11720      * **Note:** This method is loosely based on
11721      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
11722      *
11723      * @static
11724      * @memberOf _
11725      * @since 4.0.0
11726      * @category Lang
11727      * @param {*} value The value to check.
11728      * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
11729      * @example
11730      *
11731      * _.isLength(3);
11732      * // => true
11733      *
11734      * _.isLength(Number.MIN_VALUE);
11735      * // => false
11736      *
11737      * _.isLength(Infinity);
11738      * // => false
11739      *
11740      * _.isLength('3');
11741      * // => false
11742      */
11743     function isLength(value) {
11744       return typeof value == 'number' &&
11745         value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
11746     }
11747
11748     /**
11749      * Checks if `value` is the
11750      * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
11751      * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
11752      *
11753      * @static
11754      * @memberOf _
11755      * @since 0.1.0
11756      * @category Lang
11757      * @param {*} value The value to check.
11758      * @returns {boolean} Returns `true` if `value` is an object, else `false`.
11759      * @example
11760      *
11761      * _.isObject({});
11762      * // => true
11763      *
11764      * _.isObject([1, 2, 3]);
11765      * // => true
11766      *
11767      * _.isObject(_.noop);
11768      * // => true
11769      *
11770      * _.isObject(null);
11771      * // => false
11772      */
11773     function isObject(value) {
11774       var type = typeof value;
11775       return value != null && (type == 'object' || type == 'function');
11776     }
11777
11778     /**
11779      * Checks if `value` is object-like. A value is object-like if it's not `null`
11780      * and has a `typeof` result of "object".
11781      *
11782      * @static
11783      * @memberOf _
11784      * @since 4.0.0
11785      * @category Lang
11786      * @param {*} value The value to check.
11787      * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
11788      * @example
11789      *
11790      * _.isObjectLike({});
11791      * // => true
11792      *
11793      * _.isObjectLike([1, 2, 3]);
11794      * // => true
11795      *
11796      * _.isObjectLike(_.noop);
11797      * // => false
11798      *
11799      * _.isObjectLike(null);
11800      * // => false
11801      */
11802     function isObjectLike(value) {
11803       return value != null && typeof value == 'object';
11804     }
11805
11806     /**
11807      * Checks if `value` is classified as a `Map` object.
11808      *
11809      * @static
11810      * @memberOf _
11811      * @since 4.3.0
11812      * @category Lang
11813      * @param {*} value The value to check.
11814      * @returns {boolean} Returns `true` if `value` is a map, else `false`.
11815      * @example
11816      *
11817      * _.isMap(new Map);
11818      * // => true
11819      *
11820      * _.isMap(new WeakMap);
11821      * // => false
11822      */
11823     var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
11824
11825     /**
11826      * Performs a partial deep comparison between `object` and `source` to
11827      * determine if `object` contains equivalent property values.
11828      *
11829      * **Note:** This method is equivalent to `_.matches` when `source` is
11830      * partially applied.
11831      *
11832      * Partial comparisons will match empty array and empty object `source`
11833      * values against any array or object value, respectively. See `_.isEqual`
11834      * for a list of supported value comparisons.
11835      *
11836      * @static
11837      * @memberOf _
11838      * @since 3.0.0
11839      * @category Lang
11840      * @param {Object} object The object to inspect.
11841      * @param {Object} source The object of property values to match.
11842      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11843      * @example
11844      *
11845      * var object = { 'a': 1, 'b': 2 };
11846      *
11847      * _.isMatch(object, { 'b': 2 });
11848      * // => true
11849      *
11850      * _.isMatch(object, { 'b': 1 });
11851      * // => false
11852      */
11853     function isMatch(object, source) {
11854       return object === source || baseIsMatch(object, source, getMatchData(source));
11855     }
11856
11857     /**
11858      * This method is like `_.isMatch` except that it accepts `customizer` which
11859      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11860      * are handled by the method instead. The `customizer` is invoked with five
11861      * arguments: (objValue, srcValue, index|key, object, source).
11862      *
11863      * @static
11864      * @memberOf _
11865      * @since 4.0.0
11866      * @category Lang
11867      * @param {Object} object The object to inspect.
11868      * @param {Object} source The object of property values to match.
11869      * @param {Function} [customizer] The function to customize comparisons.
11870      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11871      * @example
11872      *
11873      * function isGreeting(value) {
11874      *   return /^h(?:i|ello)$/.test(value);
11875      * }
11876      *
11877      * function customizer(objValue, srcValue) {
11878      *   if (isGreeting(objValue) && isGreeting(srcValue)) {
11879      *     return true;
11880      *   }
11881      * }
11882      *
11883      * var object = { 'greeting': 'hello' };
11884      * var source = { 'greeting': 'hi' };
11885      *
11886      * _.isMatchWith(object, source, customizer);
11887      * // => true
11888      */
11889     function isMatchWith(object, source, customizer) {
11890       customizer = typeof customizer == 'function' ? customizer : undefined;
11891       return baseIsMatch(object, source, getMatchData(source), customizer);
11892     }
11893
11894     /**
11895      * Checks if `value` is `NaN`.
11896      *
11897      * **Note:** This method is based on
11898      * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
11899      * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
11900      * `undefined` and other non-number values.
11901      *
11902      * @static
11903      * @memberOf _
11904      * @since 0.1.0
11905      * @category Lang
11906      * @param {*} value The value to check.
11907      * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
11908      * @example
11909      *
11910      * _.isNaN(NaN);
11911      * // => true
11912      *
11913      * _.isNaN(new Number(NaN));
11914      * // => true
11915      *
11916      * isNaN(undefined);
11917      * // => true
11918      *
11919      * _.isNaN(undefined);
11920      * // => false
11921      */
11922     function isNaN(value) {
11923       // An `NaN` primitive is the only value that is not equal to itself.
11924       // Perform the `toStringTag` check first to avoid errors with some
11925       // ActiveX objects in IE.
11926       return isNumber(value) && value != +value;
11927     }
11928
11929     /**
11930      * Checks if `value` is a pristine native function.
11931      *
11932      * **Note:** This method can't reliably detect native functions in the presence
11933      * of the core-js package because core-js circumvents this kind of detection.
11934      * Despite multiple requests, the core-js maintainer has made it clear: any
11935      * attempt to fix the detection will be obstructed. As a result, we're left
11936      * with little choice but to throw an error. Unfortunately, this also affects
11937      * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
11938      * which rely on core-js.
11939      *
11940      * @static
11941      * @memberOf _
11942      * @since 3.0.0
11943      * @category Lang
11944      * @param {*} value The value to check.
11945      * @returns {boolean} Returns `true` if `value` is a native function,
11946      *  else `false`.
11947      * @example
11948      *
11949      * _.isNative(Array.prototype.push);
11950      * // => true
11951      *
11952      * _.isNative(_);
11953      * // => false
11954      */
11955     function isNative(value) {
11956       if (isMaskable(value)) {
11957         throw new Error(CORE_ERROR_TEXT);
11958       }
11959       return baseIsNative(value);
11960     }
11961
11962     /**
11963      * Checks if `value` is `null`.
11964      *
11965      * @static
11966      * @memberOf _
11967      * @since 0.1.0
11968      * @category Lang
11969      * @param {*} value The value to check.
11970      * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
11971      * @example
11972      *
11973      * _.isNull(null);
11974      * // => true
11975      *
11976      * _.isNull(void 0);
11977      * // => false
11978      */
11979     function isNull(value) {
11980       return value === null;
11981     }
11982
11983     /**
11984      * Checks if `value` is `null` or `undefined`.
11985      *
11986      * @static
11987      * @memberOf _
11988      * @since 4.0.0
11989      * @category Lang
11990      * @param {*} value The value to check.
11991      * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
11992      * @example
11993      *
11994      * _.isNil(null);
11995      * // => true
11996      *
11997      * _.isNil(void 0);
11998      * // => true
11999      *
12000      * _.isNil(NaN);
12001      * // => false
12002      */
12003     function isNil(value) {
12004       return value == null;
12005     }
12006
12007     /**
12008      * Checks if `value` is classified as a `Number` primitive or object.
12009      *
12010      * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
12011      * classified as numbers, use the `_.isFinite` method.
12012      *
12013      * @static
12014      * @memberOf _
12015      * @since 0.1.0
12016      * @category Lang
12017      * @param {*} value The value to check.
12018      * @returns {boolean} Returns `true` if `value` is a number, else `false`.
12019      * @example
12020      *
12021      * _.isNumber(3);
12022      * // => true
12023      *
12024      * _.isNumber(Number.MIN_VALUE);
12025      * // => true
12026      *
12027      * _.isNumber(Infinity);
12028      * // => true
12029      *
12030      * _.isNumber('3');
12031      * // => false
12032      */
12033     function isNumber(value) {
12034       return typeof value == 'number' ||
12035         (isObjectLike(value) && baseGetTag(value) == numberTag);
12036     }
12037
12038     /**
12039      * Checks if `value` is a plain object, that is, an object created by the
12040      * `Object` constructor or one with a `[[Prototype]]` of `null`.
12041      *
12042      * @static
12043      * @memberOf _
12044      * @since 0.8.0
12045      * @category Lang
12046      * @param {*} value The value to check.
12047      * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
12048      * @example
12049      *
12050      * function Foo() {
12051      *   this.a = 1;
12052      * }
12053      *
12054      * _.isPlainObject(new Foo);
12055      * // => false
12056      *
12057      * _.isPlainObject([1, 2, 3]);
12058      * // => false
12059      *
12060      * _.isPlainObject({ 'x': 0, 'y': 0 });
12061      * // => true
12062      *
12063      * _.isPlainObject(Object.create(null));
12064      * // => true
12065      */
12066     function isPlainObject(value) {
12067       if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
12068         return false;
12069       }
12070       var proto = getPrototype(value);
12071       if (proto === null) {
12072         return true;
12073       }
12074       var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
12075       return typeof Ctor == 'function' && Ctor instanceof Ctor &&
12076         funcToString.call(Ctor) == objectCtorString;
12077     }
12078
12079     /**
12080      * Checks if `value` is classified as a `RegExp` object.
12081      *
12082      * @static
12083      * @memberOf _
12084      * @since 0.1.0
12085      * @category Lang
12086      * @param {*} value The value to check.
12087      * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
12088      * @example
12089      *
12090      * _.isRegExp(/abc/);
12091      * // => true
12092      *
12093      * _.isRegExp('/abc/');
12094      * // => false
12095      */
12096     var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
12097
12098     /**
12099      * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
12100      * double precision number which isn't the result of a rounded unsafe integer.
12101      *
12102      * **Note:** This method is based on
12103      * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
12104      *
12105      * @static
12106      * @memberOf _
12107      * @since 4.0.0
12108      * @category Lang
12109      * @param {*} value The value to check.
12110      * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
12111      * @example
12112      *
12113      * _.isSafeInteger(3);
12114      * // => true
12115      *
12116      * _.isSafeInteger(Number.MIN_VALUE);
12117      * // => false
12118      *
12119      * _.isSafeInteger(Infinity);
12120      * // => false
12121      *
12122      * _.isSafeInteger('3');
12123      * // => false
12124      */
12125     function isSafeInteger(value) {
12126       return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
12127     }
12128
12129     /**
12130      * Checks if `value` is classified as a `Set` object.
12131      *
12132      * @static
12133      * @memberOf _
12134      * @since 4.3.0
12135      * @category Lang
12136      * @param {*} value The value to check.
12137      * @returns {boolean} Returns `true` if `value` is a set, else `false`.
12138      * @example
12139      *
12140      * _.isSet(new Set);
12141      * // => true
12142      *
12143      * _.isSet(new WeakSet);
12144      * // => false
12145      */
12146     var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
12147
12148     /**
12149      * Checks if `value` is classified as a `String` primitive or object.
12150      *
12151      * @static
12152      * @since 0.1.0
12153      * @memberOf _
12154      * @category Lang
12155      * @param {*} value The value to check.
12156      * @returns {boolean} Returns `true` if `value` is a string, else `false`.
12157      * @example
12158      *
12159      * _.isString('abc');
12160      * // => true
12161      *
12162      * _.isString(1);
12163      * // => false
12164      */
12165     function isString(value) {
12166       return typeof value == 'string' ||
12167         (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
12168     }
12169
12170     /**
12171      * Checks if `value` is classified as a `Symbol` primitive or object.
12172      *
12173      * @static
12174      * @memberOf _
12175      * @since 4.0.0
12176      * @category Lang
12177      * @param {*} value The value to check.
12178      * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
12179      * @example
12180      *
12181      * _.isSymbol(Symbol.iterator);
12182      * // => true
12183      *
12184      * _.isSymbol('abc');
12185      * // => false
12186      */
12187     function isSymbol(value) {
12188       return typeof value == 'symbol' ||
12189         (isObjectLike(value) && baseGetTag(value) == symbolTag);
12190     }
12191
12192     /**
12193      * Checks if `value` is classified as a typed array.
12194      *
12195      * @static
12196      * @memberOf _
12197      * @since 3.0.0
12198      * @category Lang
12199      * @param {*} value The value to check.
12200      * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
12201      * @example
12202      *
12203      * _.isTypedArray(new Uint8Array);
12204      * // => true
12205      *
12206      * _.isTypedArray([]);
12207      * // => false
12208      */
12209     var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
12210
12211     /**
12212      * Checks if `value` is `undefined`.
12213      *
12214      * @static
12215      * @since 0.1.0
12216      * @memberOf _
12217      * @category Lang
12218      * @param {*} value The value to check.
12219      * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
12220      * @example
12221      *
12222      * _.isUndefined(void 0);
12223      * // => true
12224      *
12225      * _.isUndefined(null);
12226      * // => false
12227      */
12228     function isUndefined(value) {
12229       return value === undefined;
12230     }
12231
12232     /**
12233      * Checks if `value` is classified as a `WeakMap` object.
12234      *
12235      * @static
12236      * @memberOf _
12237      * @since 4.3.0
12238      * @category Lang
12239      * @param {*} value The value to check.
12240      * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
12241      * @example
12242      *
12243      * _.isWeakMap(new WeakMap);
12244      * // => true
12245      *
12246      * _.isWeakMap(new Map);
12247      * // => false
12248      */
12249     function isWeakMap(value) {
12250       return isObjectLike(value) && getTag(value) == weakMapTag;
12251     }
12252
12253     /**
12254      * Checks if `value` is classified as a `WeakSet` object.
12255      *
12256      * @static
12257      * @memberOf _
12258      * @since 4.3.0
12259      * @category Lang
12260      * @param {*} value The value to check.
12261      * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
12262      * @example
12263      *
12264      * _.isWeakSet(new WeakSet);
12265      * // => true
12266      *
12267      * _.isWeakSet(new Set);
12268      * // => false
12269      */
12270     function isWeakSet(value) {
12271       return isObjectLike(value) && baseGetTag(value) == weakSetTag;
12272     }
12273
12274     /**
12275      * Checks if `value` is less than `other`.
12276      *
12277      * @static
12278      * @memberOf _
12279      * @since 3.9.0
12280      * @category Lang
12281      * @param {*} value The value to compare.
12282      * @param {*} other The other value to compare.
12283      * @returns {boolean} Returns `true` if `value` is less than `other`,
12284      *  else `false`.
12285      * @see _.gt
12286      * @example
12287      *
12288      * _.lt(1, 3);
12289      * // => true
12290      *
12291      * _.lt(3, 3);
12292      * // => false
12293      *
12294      * _.lt(3, 1);
12295      * // => false
12296      */
12297     var lt = createRelationalOperation(baseLt);
12298
12299     /**
12300      * Checks if `value` is less than or equal to `other`.
12301      *
12302      * @static
12303      * @memberOf _
12304      * @since 3.9.0
12305      * @category Lang
12306      * @param {*} value The value to compare.
12307      * @param {*} other The other value to compare.
12308      * @returns {boolean} Returns `true` if `value` is less than or equal to
12309      *  `other`, else `false`.
12310      * @see _.gte
12311      * @example
12312      *
12313      * _.lte(1, 3);
12314      * // => true
12315      *
12316      * _.lte(3, 3);
12317      * // => true
12318      *
12319      * _.lte(3, 1);
12320      * // => false
12321      */
12322     var lte = createRelationalOperation(function(value, other) {
12323       return value <= other;
12324     });
12325
12326     /**
12327      * Converts `value` to an array.
12328      *
12329      * @static
12330      * @since 0.1.0
12331      * @memberOf _
12332      * @category Lang
12333      * @param {*} value The value to convert.
12334      * @returns {Array} Returns the converted array.
12335      * @example
12336      *
12337      * _.toArray({ 'a': 1, 'b': 2 });
12338      * // => [1, 2]
12339      *
12340      * _.toArray('abc');
12341      * // => ['a', 'b', 'c']
12342      *
12343      * _.toArray(1);
12344      * // => []
12345      *
12346      * _.toArray(null);
12347      * // => []
12348      */
12349     function toArray(value) {
12350       if (!value) {
12351         return [];
12352       }
12353       if (isArrayLike(value)) {
12354         return isString(value) ? stringToArray(value) : copyArray(value);
12355       }
12356       if (symIterator && value[symIterator]) {
12357         return iteratorToArray(value[symIterator]());
12358       }
12359       var tag = getTag(value),
12360           func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
12361
12362       return func(value);
12363     }
12364
12365     /**
12366      * Converts `value` to a finite number.
12367      *
12368      * @static
12369      * @memberOf _
12370      * @since 4.12.0
12371      * @category Lang
12372      * @param {*} value The value to convert.
12373      * @returns {number} Returns the converted number.
12374      * @example
12375      *
12376      * _.toFinite(3.2);
12377      * // => 3.2
12378      *
12379      * _.toFinite(Number.MIN_VALUE);
12380      * // => 5e-324
12381      *
12382      * _.toFinite(Infinity);
12383      * // => 1.7976931348623157e+308
12384      *
12385      * _.toFinite('3.2');
12386      * // => 3.2
12387      */
12388     function toFinite(value) {
12389       if (!value) {
12390         return value === 0 ? value : 0;
12391       }
12392       value = toNumber(value);
12393       if (value === INFINITY || value === -INFINITY) {
12394         var sign = (value < 0 ? -1 : 1);
12395         return sign * MAX_INTEGER;
12396       }
12397       return value === value ? value : 0;
12398     }
12399
12400     /**
12401      * Converts `value` to an integer.
12402      *
12403      * **Note:** This method is loosely based on
12404      * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
12405      *
12406      * @static
12407      * @memberOf _
12408      * @since 4.0.0
12409      * @category Lang
12410      * @param {*} value The value to convert.
12411      * @returns {number} Returns the converted integer.
12412      * @example
12413      *
12414      * _.toInteger(3.2);
12415      * // => 3
12416      *
12417      * _.toInteger(Number.MIN_VALUE);
12418      * // => 0
12419      *
12420      * _.toInteger(Infinity);
12421      * // => 1.7976931348623157e+308
12422      *
12423      * _.toInteger('3.2');
12424      * // => 3
12425      */
12426     function toInteger(value) {
12427       var result = toFinite(value),
12428           remainder = result % 1;
12429
12430       return result === result ? (remainder ? result - remainder : result) : 0;
12431     }
12432
12433     /**
12434      * Converts `value` to an integer suitable for use as the length of an
12435      * array-like object.
12436      *
12437      * **Note:** This method is based on
12438      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
12439      *
12440      * @static
12441      * @memberOf _
12442      * @since 4.0.0
12443      * @category Lang
12444      * @param {*} value The value to convert.
12445      * @returns {number} Returns the converted integer.
12446      * @example
12447      *
12448      * _.toLength(3.2);
12449      * // => 3
12450      *
12451      * _.toLength(Number.MIN_VALUE);
12452      * // => 0
12453      *
12454      * _.toLength(Infinity);
12455      * // => 4294967295
12456      *
12457      * _.toLength('3.2');
12458      * // => 3
12459      */
12460     function toLength(value) {
12461       return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
12462     }
12463
12464     /**
12465      * Converts `value` to a number.
12466      *
12467      * @static
12468      * @memberOf _
12469      * @since 4.0.0
12470      * @category Lang
12471      * @param {*} value The value to process.
12472      * @returns {number} Returns the number.
12473      * @example
12474      *
12475      * _.toNumber(3.2);
12476      * // => 3.2
12477      *
12478      * _.toNumber(Number.MIN_VALUE);
12479      * // => 5e-324
12480      *
12481      * _.toNumber(Infinity);
12482      * // => Infinity
12483      *
12484      * _.toNumber('3.2');
12485      * // => 3.2
12486      */
12487     function toNumber(value) {
12488       if (typeof value == 'number') {
12489         return value;
12490       }
12491       if (isSymbol(value)) {
12492         return NAN;
12493       }
12494       if (isObject(value)) {
12495         var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
12496         value = isObject(other) ? (other + '') : other;
12497       }
12498       if (typeof value != 'string') {
12499         return value === 0 ? value : +value;
12500       }
12501       value = value.replace(reTrim, '');
12502       var isBinary = reIsBinary.test(value);
12503       return (isBinary || reIsOctal.test(value))
12504         ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
12505         : (reIsBadHex.test(value) ? NAN : +value);
12506     }
12507
12508     /**
12509      * Converts `value` to a plain object flattening inherited enumerable string
12510      * keyed properties of `value` to own properties of the plain object.
12511      *
12512      * @static
12513      * @memberOf _
12514      * @since 3.0.0
12515      * @category Lang
12516      * @param {*} value The value to convert.
12517      * @returns {Object} Returns the converted plain object.
12518      * @example
12519      *
12520      * function Foo() {
12521      *   this.b = 2;
12522      * }
12523      *
12524      * Foo.prototype.c = 3;
12525      *
12526      * _.assign({ 'a': 1 }, new Foo);
12527      * // => { 'a': 1, 'b': 2 }
12528      *
12529      * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
12530      * // => { 'a': 1, 'b': 2, 'c': 3 }
12531      */
12532     function toPlainObject(value) {
12533       return copyObject(value, keysIn(value));
12534     }
12535
12536     /**
12537      * Converts `value` to a safe integer. A safe integer can be compared and
12538      * represented correctly.
12539      *
12540      * @static
12541      * @memberOf _
12542      * @since 4.0.0
12543      * @category Lang
12544      * @param {*} value The value to convert.
12545      * @returns {number} Returns the converted integer.
12546      * @example
12547      *
12548      * _.toSafeInteger(3.2);
12549      * // => 3
12550      *
12551      * _.toSafeInteger(Number.MIN_VALUE);
12552      * // => 0
12553      *
12554      * _.toSafeInteger(Infinity);
12555      * // => 9007199254740991
12556      *
12557      * _.toSafeInteger('3.2');
12558      * // => 3
12559      */
12560     function toSafeInteger(value) {
12561       return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);
12562     }
12563
12564     /**
12565      * Converts `value` to a string. An empty string is returned for `null`
12566      * and `undefined` values. The sign of `-0` is preserved.
12567      *
12568      * @static
12569      * @memberOf _
12570      * @since 4.0.0
12571      * @category Lang
12572      * @param {*} value The value to convert.
12573      * @returns {string} Returns the converted string.
12574      * @example
12575      *
12576      * _.toString(null);
12577      * // => ''
12578      *
12579      * _.toString(-0);
12580      * // => '-0'
12581      *
12582      * _.toString([1, 2, 3]);
12583      * // => '1,2,3'
12584      */
12585     function toString(value) {
12586       return value == null ? '' : baseToString(value);
12587     }
12588
12589     /*------------------------------------------------------------------------*/
12590
12591     /**
12592      * Assigns own enumerable string keyed properties of source objects to the
12593      * destination object. Source objects are applied from left to right.
12594      * Subsequent sources overwrite property assignments of previous sources.
12595      *
12596      * **Note:** This method mutates `object` and is loosely based on
12597      * [`Object.assign`](https://mdn.io/Object/assign).
12598      *
12599      * @static
12600      * @memberOf _
12601      * @since 0.10.0
12602      * @category Object
12603      * @param {Object} object The destination object.
12604      * @param {...Object} [sources] The source objects.
12605      * @returns {Object} Returns `object`.
12606      * @see _.assignIn
12607      * @example
12608      *
12609      * function Foo() {
12610      *   this.a = 1;
12611      * }
12612      *
12613      * function Bar() {
12614      *   this.c = 3;
12615      * }
12616      *
12617      * Foo.prototype.b = 2;
12618      * Bar.prototype.d = 4;
12619      *
12620      * _.assign({ 'a': 0 }, new Foo, new Bar);
12621      * // => { 'a': 1, 'c': 3 }
12622      */
12623     var assign = createAssigner(function(object, source) {
12624       if (isPrototype(source) || isArrayLike(source)) {
12625         copyObject(source, keys(source), object);
12626         return;
12627       }
12628       for (var key in source) {
12629         if (hasOwnProperty.call(source, key)) {
12630           assignValue(object, key, source[key]);
12631         }
12632       }
12633     });
12634
12635     /**
12636      * This method is like `_.assign` except that it iterates over own and
12637      * inherited source properties.
12638      *
12639      * **Note:** This method mutates `object`.
12640      *
12641      * @static
12642      * @memberOf _
12643      * @since 4.0.0
12644      * @alias extend
12645      * @category Object
12646      * @param {Object} object The destination object.
12647      * @param {...Object} [sources] The source objects.
12648      * @returns {Object} Returns `object`.
12649      * @see _.assign
12650      * @example
12651      *
12652      * function Foo() {
12653      *   this.a = 1;
12654      * }
12655      *
12656      * function Bar() {
12657      *   this.c = 3;
12658      * }
12659      *
12660      * Foo.prototype.b = 2;
12661      * Bar.prototype.d = 4;
12662      *
12663      * _.assignIn({ 'a': 0 }, new Foo, new Bar);
12664      * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
12665      */
12666     var assignIn = createAssigner(function(object, source) {
12667       copyObject(source, keysIn(source), object);
12668     });
12669
12670     /**
12671      * This method is like `_.assignIn` except that it accepts `customizer`
12672      * which is invoked to produce the assigned values. If `customizer` returns
12673      * `undefined`, assignment is handled by the method instead. The `customizer`
12674      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12675      *
12676      * **Note:** This method mutates `object`.
12677      *
12678      * @static
12679      * @memberOf _
12680      * @since 4.0.0
12681      * @alias extendWith
12682      * @category Object
12683      * @param {Object} object The destination object.
12684      * @param {...Object} sources The source objects.
12685      * @param {Function} [customizer] The function to customize assigned values.
12686      * @returns {Object} Returns `object`.
12687      * @see _.assignWith
12688      * @example
12689      *
12690      * function customizer(objValue, srcValue) {
12691      *   return _.isUndefined(objValue) ? srcValue : objValue;
12692      * }
12693      *
12694      * var defaults = _.partialRight(_.assignInWith, customizer);
12695      *
12696      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12697      * // => { 'a': 1, 'b': 2 }
12698      */
12699     var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
12700       copyObject(source, keysIn(source), object, customizer);
12701     });
12702
12703     /**
12704      * This method is like `_.assign` except that it accepts `customizer`
12705      * which is invoked to produce the assigned values. If `customizer` returns
12706      * `undefined`, assignment is handled by the method instead. The `customizer`
12707      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12708      *
12709      * **Note:** This method mutates `object`.
12710      *
12711      * @static
12712      * @memberOf _
12713      * @since 4.0.0
12714      * @category Object
12715      * @param {Object} object The destination object.
12716      * @param {...Object} sources The source objects.
12717      * @param {Function} [customizer] The function to customize assigned values.
12718      * @returns {Object} Returns `object`.
12719      * @see _.assignInWith
12720      * @example
12721      *
12722      * function customizer(objValue, srcValue) {
12723      *   return _.isUndefined(objValue) ? srcValue : objValue;
12724      * }
12725      *
12726      * var defaults = _.partialRight(_.assignWith, customizer);
12727      *
12728      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12729      * // => { 'a': 1, 'b': 2 }
12730      */
12731     var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
12732       copyObject(source, keys(source), object, customizer);
12733     });
12734
12735     /**
12736      * Creates an array of values corresponding to `paths` of `object`.
12737      *
12738      * @static
12739      * @memberOf _
12740      * @since 1.0.0
12741      * @category Object
12742      * @param {Object} object The object to iterate over.
12743      * @param {...(string|string[])} [paths] The property paths to pick.
12744      * @returns {Array} Returns the picked values.
12745      * @example
12746      *
12747      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
12748      *
12749      * _.at(object, ['a[0].b.c', 'a[1]']);
12750      * // => [3, 4]
12751      */
12752     var at = flatRest(baseAt);
12753
12754     /**
12755      * Creates an object that inherits from the `prototype` object. If a
12756      * `properties` object is given, its own enumerable string keyed properties
12757      * are assigned to the created object.
12758      *
12759      * @static
12760      * @memberOf _
12761      * @since 2.3.0
12762      * @category Object
12763      * @param {Object} prototype The object to inherit from.
12764      * @param {Object} [properties] The properties to assign to the object.
12765      * @returns {Object} Returns the new object.
12766      * @example
12767      *
12768      * function Shape() {
12769      *   this.x = 0;
12770      *   this.y = 0;
12771      * }
12772      *
12773      * function Circle() {
12774      *   Shape.call(this);
12775      * }
12776      *
12777      * Circle.prototype = _.create(Shape.prototype, {
12778      *   'constructor': Circle
12779      * });
12780      *
12781      * var circle = new Circle;
12782      * circle instanceof Circle;
12783      * // => true
12784      *
12785      * circle instanceof Shape;
12786      * // => true
12787      */
12788     function create(prototype, properties) {
12789       var result = baseCreate(prototype);
12790       return properties == null ? result : baseAssign(result, properties);
12791     }
12792
12793     /**
12794      * Assigns own and inherited enumerable string keyed properties of source
12795      * objects to the destination object for all destination properties that
12796      * resolve to `undefined`. Source objects are applied from left to right.
12797      * Once a property is set, additional values of the same property are ignored.
12798      *
12799      * **Note:** This method mutates `object`.
12800      *
12801      * @static
12802      * @since 0.1.0
12803      * @memberOf _
12804      * @category Object
12805      * @param {Object} object The destination object.
12806      * @param {...Object} [sources] The source objects.
12807      * @returns {Object} Returns `object`.
12808      * @see _.defaultsDeep
12809      * @example
12810      *
12811      * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12812      * // => { 'a': 1, 'b': 2 }
12813      */
12814     var defaults = baseRest(function(args) {
12815       args.push(undefined, assignInDefaults);
12816       return apply(assignInWith, undefined, args);
12817     });
12818
12819     /**
12820      * This method is like `_.defaults` except that it recursively assigns
12821      * default properties.
12822      *
12823      * **Note:** This method mutates `object`.
12824      *
12825      * @static
12826      * @memberOf _
12827      * @since 3.10.0
12828      * @category Object
12829      * @param {Object} object The destination object.
12830      * @param {...Object} [sources] The source objects.
12831      * @returns {Object} Returns `object`.
12832      * @see _.defaults
12833      * @example
12834      *
12835      * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
12836      * // => { 'a': { 'b': 2, 'c': 3 } }
12837      */
12838     var defaultsDeep = baseRest(function(args) {
12839       args.push(undefined, mergeDefaults);
12840       return apply(mergeWith, undefined, args);
12841     });
12842
12843     /**
12844      * This method is like `_.find` except that it returns the key of the first
12845      * element `predicate` returns truthy for instead of the element itself.
12846      *
12847      * @static
12848      * @memberOf _
12849      * @since 1.1.0
12850      * @category Object
12851      * @param {Object} object The object to inspect.
12852      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12853      * @returns {string|undefined} Returns the key of the matched element,
12854      *  else `undefined`.
12855      * @example
12856      *
12857      * var users = {
12858      *   'barney':  { 'age': 36, 'active': true },
12859      *   'fred':    { 'age': 40, 'active': false },
12860      *   'pebbles': { 'age': 1,  'active': true }
12861      * };
12862      *
12863      * _.findKey(users, function(o) { return o.age < 40; });
12864      * // => 'barney' (iteration order is not guaranteed)
12865      *
12866      * // The `_.matches` iteratee shorthand.
12867      * _.findKey(users, { 'age': 1, 'active': true });
12868      * // => 'pebbles'
12869      *
12870      * // The `_.matchesProperty` iteratee shorthand.
12871      * _.findKey(users, ['active', false]);
12872      * // => 'fred'
12873      *
12874      * // The `_.property` iteratee shorthand.
12875      * _.findKey(users, 'active');
12876      * // => 'barney'
12877      */
12878     function findKey(object, predicate) {
12879       return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
12880     }
12881
12882     /**
12883      * This method is like `_.findKey` except that it iterates over elements of
12884      * a collection in the opposite order.
12885      *
12886      * @static
12887      * @memberOf _
12888      * @since 2.0.0
12889      * @category Object
12890      * @param {Object} object The object to inspect.
12891      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12892      * @returns {string|undefined} Returns the key of the matched element,
12893      *  else `undefined`.
12894      * @example
12895      *
12896      * var users = {
12897      *   'barney':  { 'age': 36, 'active': true },
12898      *   'fred':    { 'age': 40, 'active': false },
12899      *   'pebbles': { 'age': 1,  'active': true }
12900      * };
12901      *
12902      * _.findLastKey(users, function(o) { return o.age < 40; });
12903      * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
12904      *
12905      * // The `_.matches` iteratee shorthand.
12906      * _.findLastKey(users, { 'age': 36, 'active': true });
12907      * // => 'barney'
12908      *
12909      * // The `_.matchesProperty` iteratee shorthand.
12910      * _.findLastKey(users, ['active', false]);
12911      * // => 'fred'
12912      *
12913      * // The `_.property` iteratee shorthand.
12914      * _.findLastKey(users, 'active');
12915      * // => 'pebbles'
12916      */
12917     function findLastKey(object, predicate) {
12918       return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
12919     }
12920
12921     /**
12922      * Iterates over own and inherited enumerable string keyed properties of an
12923      * object and invokes `iteratee` for each property. The iteratee is invoked
12924      * with three arguments: (value, key, object). Iteratee functions may exit
12925      * iteration early by explicitly returning `false`.
12926      *
12927      * @static
12928      * @memberOf _
12929      * @since 0.3.0
12930      * @category Object
12931      * @param {Object} object The object to iterate over.
12932      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12933      * @returns {Object} Returns `object`.
12934      * @see _.forInRight
12935      * @example
12936      *
12937      * function Foo() {
12938      *   this.a = 1;
12939      *   this.b = 2;
12940      * }
12941      *
12942      * Foo.prototype.c = 3;
12943      *
12944      * _.forIn(new Foo, function(value, key) {
12945      *   console.log(key);
12946      * });
12947      * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
12948      */
12949     function forIn(object, iteratee) {
12950       return object == null
12951         ? object
12952         : baseFor(object, getIteratee(iteratee, 3), keysIn);
12953     }
12954
12955     /**
12956      * This method is like `_.forIn` except that it iterates over properties of
12957      * `object` in the opposite order.
12958      *
12959      * @static
12960      * @memberOf _
12961      * @since 2.0.0
12962      * @category Object
12963      * @param {Object} object The object to iterate over.
12964      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12965      * @returns {Object} Returns `object`.
12966      * @see _.forIn
12967      * @example
12968      *
12969      * function Foo() {
12970      *   this.a = 1;
12971      *   this.b = 2;
12972      * }
12973      *
12974      * Foo.prototype.c = 3;
12975      *
12976      * _.forInRight(new Foo, function(value, key) {
12977      *   console.log(key);
12978      * });
12979      * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
12980      */
12981     function forInRight(object, iteratee) {
12982       return object == null
12983         ? object
12984         : baseForRight(object, getIteratee(iteratee, 3), keysIn);
12985     }
12986
12987     /**
12988      * Iterates over own enumerable string keyed properties of an object and
12989      * invokes `iteratee` for each property. The iteratee is invoked with three
12990      * arguments: (value, key, object). Iteratee functions may exit iteration
12991      * early by explicitly returning `false`.
12992      *
12993      * @static
12994      * @memberOf _
12995      * @since 0.3.0
12996      * @category Object
12997      * @param {Object} object The object to iterate over.
12998      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12999      * @returns {Object} Returns `object`.
13000      * @see _.forOwnRight
13001      * @example
13002      *
13003      * function Foo() {
13004      *   this.a = 1;
13005      *   this.b = 2;
13006      * }
13007      *
13008      * Foo.prototype.c = 3;
13009      *
13010      * _.forOwn(new Foo, function(value, key) {
13011      *   console.log(key);
13012      * });
13013      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
13014      */
13015     function forOwn(object, iteratee) {
13016       return object && baseForOwn(object, getIteratee(iteratee, 3));
13017     }
13018
13019     /**
13020      * This method is like `_.forOwn` except that it iterates over properties of
13021      * `object` in the opposite order.
13022      *
13023      * @static
13024      * @memberOf _
13025      * @since 2.0.0
13026      * @category Object
13027      * @param {Object} object The object to iterate over.
13028      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13029      * @returns {Object} Returns `object`.
13030      * @see _.forOwn
13031      * @example
13032      *
13033      * function Foo() {
13034      *   this.a = 1;
13035      *   this.b = 2;
13036      * }
13037      *
13038      * Foo.prototype.c = 3;
13039      *
13040      * _.forOwnRight(new Foo, function(value, key) {
13041      *   console.log(key);
13042      * });
13043      * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
13044      */
13045     function forOwnRight(object, iteratee) {
13046       return object && baseForOwnRight(object, getIteratee(iteratee, 3));
13047     }
13048
13049     /**
13050      * Creates an array of function property names from own enumerable properties
13051      * of `object`.
13052      *
13053      * @static
13054      * @since 0.1.0
13055      * @memberOf _
13056      * @category Object
13057      * @param {Object} object The object to inspect.
13058      * @returns {Array} Returns the function names.
13059      * @see _.functionsIn
13060      * @example
13061      *
13062      * function Foo() {
13063      *   this.a = _.constant('a');
13064      *   this.b = _.constant('b');
13065      * }
13066      *
13067      * Foo.prototype.c = _.constant('c');
13068      *
13069      * _.functions(new Foo);
13070      * // => ['a', 'b']
13071      */
13072     function functions(object) {
13073       return object == null ? [] : baseFunctions(object, keys(object));
13074     }
13075
13076     /**
13077      * Creates an array of function property names from own and inherited
13078      * enumerable properties of `object`.
13079      *
13080      * @static
13081      * @memberOf _
13082      * @since 4.0.0
13083      * @category Object
13084      * @param {Object} object The object to inspect.
13085      * @returns {Array} Returns the function names.
13086      * @see _.functions
13087      * @example
13088      *
13089      * function Foo() {
13090      *   this.a = _.constant('a');
13091      *   this.b = _.constant('b');
13092      * }
13093      *
13094      * Foo.prototype.c = _.constant('c');
13095      *
13096      * _.functionsIn(new Foo);
13097      * // => ['a', 'b', 'c']
13098      */
13099     function functionsIn(object) {
13100       return object == null ? [] : baseFunctions(object, keysIn(object));
13101     }
13102
13103     /**
13104      * Gets the value at `path` of `object`. If the resolved value is
13105      * `undefined`, the `defaultValue` is returned in its place.
13106      *
13107      * @static
13108      * @memberOf _
13109      * @since 3.7.0
13110      * @category Object
13111      * @param {Object} object The object to query.
13112      * @param {Array|string} path The path of the property to get.
13113      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13114      * @returns {*} Returns the resolved value.
13115      * @example
13116      *
13117      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13118      *
13119      * _.get(object, 'a[0].b.c');
13120      * // => 3
13121      *
13122      * _.get(object, ['a', '0', 'b', 'c']);
13123      * // => 3
13124      *
13125      * _.get(object, 'a.b.c', 'default');
13126      * // => 'default'
13127      */
13128     function get(object, path, defaultValue) {
13129       var result = object == null ? undefined : baseGet(object, path);
13130       return result === undefined ? defaultValue : result;
13131     }
13132
13133     /**
13134      * Checks if `path` is a direct property of `object`.
13135      *
13136      * @static
13137      * @since 0.1.0
13138      * @memberOf _
13139      * @category Object
13140      * @param {Object} object The object to query.
13141      * @param {Array|string} path The path to check.
13142      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13143      * @example
13144      *
13145      * var object = { 'a': { 'b': 2 } };
13146      * var other = _.create({ 'a': _.create({ 'b': 2 }) });
13147      *
13148      * _.has(object, 'a');
13149      * // => true
13150      *
13151      * _.has(object, 'a.b');
13152      * // => true
13153      *
13154      * _.has(object, ['a', 'b']);
13155      * // => true
13156      *
13157      * _.has(other, 'a');
13158      * // => false
13159      */
13160     function has(object, path) {
13161       return object != null && hasPath(object, path, baseHas);
13162     }
13163
13164     /**
13165      * Checks if `path` is a direct or inherited property of `object`.
13166      *
13167      * @static
13168      * @memberOf _
13169      * @since 4.0.0
13170      * @category Object
13171      * @param {Object} object The object to query.
13172      * @param {Array|string} path The path to check.
13173      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13174      * @example
13175      *
13176      * var object = _.create({ 'a': _.create({ 'b': 2 }) });
13177      *
13178      * _.hasIn(object, 'a');
13179      * // => true
13180      *
13181      * _.hasIn(object, 'a.b');
13182      * // => true
13183      *
13184      * _.hasIn(object, ['a', 'b']);
13185      * // => true
13186      *
13187      * _.hasIn(object, 'b');
13188      * // => false
13189      */
13190     function hasIn(object, path) {
13191       return object != null && hasPath(object, path, baseHasIn);
13192     }
13193
13194     /**
13195      * Creates an object composed of the inverted keys and values of `object`.
13196      * If `object` contains duplicate values, subsequent values overwrite
13197      * property assignments of previous values.
13198      *
13199      * @static
13200      * @memberOf _
13201      * @since 0.7.0
13202      * @category Object
13203      * @param {Object} object The object to invert.
13204      * @returns {Object} Returns the new inverted object.
13205      * @example
13206      *
13207      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13208      *
13209      * _.invert(object);
13210      * // => { '1': 'c', '2': 'b' }
13211      */
13212     var invert = createInverter(function(result, value, key) {
13213       result[value] = key;
13214     }, constant(identity));
13215
13216     /**
13217      * This method is like `_.invert` except that the inverted object is generated
13218      * from the results of running each element of `object` thru `iteratee`. The
13219      * corresponding inverted value of each inverted key is an array of keys
13220      * responsible for generating the inverted value. The iteratee is invoked
13221      * with one argument: (value).
13222      *
13223      * @static
13224      * @memberOf _
13225      * @since 4.1.0
13226      * @category Object
13227      * @param {Object} object The object to invert.
13228      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
13229      * @returns {Object} Returns the new inverted object.
13230      * @example
13231      *
13232      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13233      *
13234      * _.invertBy(object);
13235      * // => { '1': ['a', 'c'], '2': ['b'] }
13236      *
13237      * _.invertBy(object, function(value) {
13238      *   return 'group' + value;
13239      * });
13240      * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
13241      */
13242     var invertBy = createInverter(function(result, value, key) {
13243       if (hasOwnProperty.call(result, value)) {
13244         result[value].push(key);
13245       } else {
13246         result[value] = [key];
13247       }
13248     }, getIteratee);
13249
13250     /**
13251      * Invokes the method at `path` of `object`.
13252      *
13253      * @static
13254      * @memberOf _
13255      * @since 4.0.0
13256      * @category Object
13257      * @param {Object} object The object to query.
13258      * @param {Array|string} path The path of the method to invoke.
13259      * @param {...*} [args] The arguments to invoke the method with.
13260      * @returns {*} Returns the result of the invoked method.
13261      * @example
13262      *
13263      * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
13264      *
13265      * _.invoke(object, 'a[0].b.c.slice', 1, 3);
13266      * // => [2, 3]
13267      */
13268     var invoke = baseRest(baseInvoke);
13269
13270     /**
13271      * Creates an array of the own enumerable property names of `object`.
13272      *
13273      * **Note:** Non-object values are coerced to objects. See the
13274      * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
13275      * for more details.
13276      *
13277      * @static
13278      * @since 0.1.0
13279      * @memberOf _
13280      * @category Object
13281      * @param {Object} object The object to query.
13282      * @returns {Array} Returns the array of property names.
13283      * @example
13284      *
13285      * function Foo() {
13286      *   this.a = 1;
13287      *   this.b = 2;
13288      * }
13289      *
13290      * Foo.prototype.c = 3;
13291      *
13292      * _.keys(new Foo);
13293      * // => ['a', 'b'] (iteration order is not guaranteed)
13294      *
13295      * _.keys('hi');
13296      * // => ['0', '1']
13297      */
13298     function keys(object) {
13299       return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
13300     }
13301
13302     /**
13303      * Creates an array of the own and inherited enumerable property names of `object`.
13304      *
13305      * **Note:** Non-object values are coerced to objects.
13306      *
13307      * @static
13308      * @memberOf _
13309      * @since 3.0.0
13310      * @category Object
13311      * @param {Object} object The object to query.
13312      * @returns {Array} Returns the array of property names.
13313      * @example
13314      *
13315      * function Foo() {
13316      *   this.a = 1;
13317      *   this.b = 2;
13318      * }
13319      *
13320      * Foo.prototype.c = 3;
13321      *
13322      * _.keysIn(new Foo);
13323      * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
13324      */
13325     function keysIn(object) {
13326       return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
13327     }
13328
13329     /**
13330      * The opposite of `_.mapValues`; this method creates an object with the
13331      * same values as `object` and keys generated by running each own enumerable
13332      * string keyed property of `object` thru `iteratee`. The iteratee is invoked
13333      * with three arguments: (value, key, object).
13334      *
13335      * @static
13336      * @memberOf _
13337      * @since 3.8.0
13338      * @category Object
13339      * @param {Object} object The object to iterate over.
13340      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13341      * @returns {Object} Returns the new mapped object.
13342      * @see _.mapValues
13343      * @example
13344      *
13345      * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
13346      *   return key + value;
13347      * });
13348      * // => { 'a1': 1, 'b2': 2 }
13349      */
13350     function mapKeys(object, iteratee) {
13351       var result = {};
13352       iteratee = getIteratee(iteratee, 3);
13353
13354       baseForOwn(object, function(value, key, object) {
13355         baseAssignValue(result, iteratee(value, key, object), value);
13356       });
13357       return result;
13358     }
13359
13360     /**
13361      * Creates an object with the same keys as `object` and values generated
13362      * by running each own enumerable string keyed property of `object` thru
13363      * `iteratee`. The iteratee is invoked with three arguments:
13364      * (value, key, object).
13365      *
13366      * @static
13367      * @memberOf _
13368      * @since 2.4.0
13369      * @category Object
13370      * @param {Object} object The object to iterate over.
13371      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13372      * @returns {Object} Returns the new mapped object.
13373      * @see _.mapKeys
13374      * @example
13375      *
13376      * var users = {
13377      *   'fred':    { 'user': 'fred',    'age': 40 },
13378      *   'pebbles': { 'user': 'pebbles', 'age': 1 }
13379      * };
13380      *
13381      * _.mapValues(users, function(o) { return o.age; });
13382      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13383      *
13384      * // The `_.property` iteratee shorthand.
13385      * _.mapValues(users, 'age');
13386      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13387      */
13388     function mapValues(object, iteratee) {
13389       var result = {};
13390       iteratee = getIteratee(iteratee, 3);
13391
13392       baseForOwn(object, function(value, key, object) {
13393         baseAssignValue(result, key, iteratee(value, key, object));
13394       });
13395       return result;
13396     }
13397
13398     /**
13399      * This method is like `_.assign` except that it recursively merges own and
13400      * inherited enumerable string keyed properties of source objects into the
13401      * destination object. Source properties that resolve to `undefined` are
13402      * skipped if a destination value exists. Array and plain object properties
13403      * are merged recursively. Other objects and value types are overridden by
13404      * assignment. Source objects are applied from left to right. Subsequent
13405      * sources overwrite property assignments of previous sources.
13406      *
13407      * **Note:** This method mutates `object`.
13408      *
13409      * @static
13410      * @memberOf _
13411      * @since 0.5.0
13412      * @category Object
13413      * @param {Object} object The destination object.
13414      * @param {...Object} [sources] The source objects.
13415      * @returns {Object} Returns `object`.
13416      * @example
13417      *
13418      * var object = {
13419      *   'a': [{ 'b': 2 }, { 'd': 4 }]
13420      * };
13421      *
13422      * var other = {
13423      *   'a': [{ 'c': 3 }, { 'e': 5 }]
13424      * };
13425      *
13426      * _.merge(object, other);
13427      * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
13428      */
13429     var merge = createAssigner(function(object, source, srcIndex) {
13430       baseMerge(object, source, srcIndex);
13431     });
13432
13433     /**
13434      * This method is like `_.merge` except that it accepts `customizer` which
13435      * is invoked to produce the merged values of the destination and source
13436      * properties. If `customizer` returns `undefined`, merging is handled by the
13437      * method instead. The `customizer` is invoked with six arguments:
13438      * (objValue, srcValue, key, object, source, stack).
13439      *
13440      * **Note:** This method mutates `object`.
13441      *
13442      * @static
13443      * @memberOf _
13444      * @since 4.0.0
13445      * @category Object
13446      * @param {Object} object The destination object.
13447      * @param {...Object} sources The source objects.
13448      * @param {Function} customizer The function to customize assigned values.
13449      * @returns {Object} Returns `object`.
13450      * @example
13451      *
13452      * function customizer(objValue, srcValue) {
13453      *   if (_.isArray(objValue)) {
13454      *     return objValue.concat(srcValue);
13455      *   }
13456      * }
13457      *
13458      * var object = { 'a': [1], 'b': [2] };
13459      * var other = { 'a': [3], 'b': [4] };
13460      *
13461      * _.mergeWith(object, other, customizer);
13462      * // => { 'a': [1, 3], 'b': [2, 4] }
13463      */
13464     var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
13465       baseMerge(object, source, srcIndex, customizer);
13466     });
13467
13468     /**
13469      * The opposite of `_.pick`; this method creates an object composed of the
13470      * own and inherited enumerable property paths of `object` that are not omitted.
13471      *
13472      * **Note:** This method is considerably slower than `_.pick`.
13473      *
13474      * @static
13475      * @since 0.1.0
13476      * @memberOf _
13477      * @category Object
13478      * @param {Object} object The source object.
13479      * @param {...(string|string[])} [paths] The property paths to omit.
13480      * @returns {Object} Returns the new object.
13481      * @example
13482      *
13483      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13484      *
13485      * _.omit(object, ['a', 'c']);
13486      * // => { 'b': '2' }
13487      */
13488     var omit = flatRest(function(object, paths) {
13489       var result = {};
13490       if (object == null) {
13491         return result;
13492       }
13493       var bitmask = CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG;
13494       paths = arrayMap(paths, function(path) {
13495         path = castPath(path, object);
13496         bitmask |= (path.length > 1 ? CLONE_DEEP_FLAG : 0);
13497         return path;
13498       });
13499
13500       copyObject(object, getAllKeysIn(object), result);
13501       result = baseClone(result, bitmask);
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, paths);
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       if (object == null) {
13575         return {};
13576       }
13577       var props = arrayMap(getAllKeysIn(object), function(prop) {
13578         return [prop];
13579       });
13580       predicate = getIteratee(predicate);
13581       return basePickBy(object, props, function(value, path) {
13582         return predicate(value, path[0]);
13583       });
13584     }
13585
13586     /**
13587      * This method is like `_.get` except that if the resolved value is a
13588      * function it's invoked with the `this` binding of its parent object and
13589      * its result is returned.
13590      *
13591      * @static
13592      * @since 0.1.0
13593      * @memberOf _
13594      * @category Object
13595      * @param {Object} object The object to query.
13596      * @param {Array|string} path The path of the property to resolve.
13597      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13598      * @returns {*} Returns the resolved value.
13599      * @example
13600      *
13601      * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
13602      *
13603      * _.result(object, 'a[0].b.c1');
13604      * // => 3
13605      *
13606      * _.result(object, 'a[0].b.c2');
13607      * // => 4
13608      *
13609      * _.result(object, 'a[0].b.c3', 'default');
13610      * // => 'default'
13611      *
13612      * _.result(object, 'a[0].b.c3', _.constant('default'));
13613      * // => 'default'
13614      */
13615     function result(object, path, defaultValue) {
13616       path = castPath(path, object);
13617
13618       var index = -1,
13619           length = path.length;
13620
13621       // Ensure the loop is entered when path is empty.
13622       if (!length) {
13623         object = undefined;
13624         length = 1;
13625       }
13626       while (++index < length) {
13627         var value = object == null ? undefined : object[toKey(path[index])];
13628         if (value === undefined) {
13629           index = length;
13630           value = defaultValue;
13631         }
13632         object = isFunction(value) ? value.call(object) : value;
13633       }
13634       return object;
13635     }
13636
13637     /**
13638      * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
13639      * it's created. Arrays are created for missing index properties while objects
13640      * are created for all other missing properties. Use `_.setWith` to customize
13641      * `path` creation.
13642      *
13643      * **Note:** This method mutates `object`.
13644      *
13645      * @static
13646      * @memberOf _
13647      * @since 3.7.0
13648      * @category Object
13649      * @param {Object} object The object to modify.
13650      * @param {Array|string} path The path of the property to set.
13651      * @param {*} value The value to set.
13652      * @returns {Object} Returns `object`.
13653      * @example
13654      *
13655      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13656      *
13657      * _.set(object, 'a[0].b.c', 4);
13658      * console.log(object.a[0].b.c);
13659      * // => 4
13660      *
13661      * _.set(object, ['x', '0', 'y', 'z'], 5);
13662      * console.log(object.x[0].y.z);
13663      * // => 5
13664      */
13665     function set(object, path, value) {
13666       return object == null ? object : baseSet(object, path, value);
13667     }
13668
13669     /**
13670      * This method is like `_.set` except that it accepts `customizer` which is
13671      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13672      * path creation is handled by the method instead. The `customizer` is invoked
13673      * with three arguments: (nsValue, key, nsObject).
13674      *
13675      * **Note:** This method mutates `object`.
13676      *
13677      * @static
13678      * @memberOf _
13679      * @since 4.0.0
13680      * @category Object
13681      * @param {Object} object The object to modify.
13682      * @param {Array|string} path The path of the property to set.
13683      * @param {*} value The value to set.
13684      * @param {Function} [customizer] The function to customize assigned values.
13685      * @returns {Object} Returns `object`.
13686      * @example
13687      *
13688      * var object = {};
13689      *
13690      * _.setWith(object, '[0][1]', 'a', Object);
13691      * // => { '0': { '1': 'a' } }
13692      */
13693     function setWith(object, path, value, customizer) {
13694       customizer = typeof customizer == 'function' ? customizer : undefined;
13695       return object == null ? object : baseSet(object, path, value, customizer);
13696     }
13697
13698     /**
13699      * Creates an array of own enumerable string keyed-value pairs for `object`
13700      * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
13701      * entries are returned.
13702      *
13703      * @static
13704      * @memberOf _
13705      * @since 4.0.0
13706      * @alias entries
13707      * @category Object
13708      * @param {Object} object The object to query.
13709      * @returns {Array} Returns the key-value pairs.
13710      * @example
13711      *
13712      * function Foo() {
13713      *   this.a = 1;
13714      *   this.b = 2;
13715      * }
13716      *
13717      * Foo.prototype.c = 3;
13718      *
13719      * _.toPairs(new Foo);
13720      * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
13721      */
13722     var toPairs = createToPairs(keys);
13723
13724     /**
13725      * Creates an array of own and inherited enumerable string keyed-value pairs
13726      * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
13727      * or set, its entries are returned.
13728      *
13729      * @static
13730      * @memberOf _
13731      * @since 4.0.0
13732      * @alias entriesIn
13733      * @category Object
13734      * @param {Object} object The object to query.
13735      * @returns {Array} Returns the key-value pairs.
13736      * @example
13737      *
13738      * function Foo() {
13739      *   this.a = 1;
13740      *   this.b = 2;
13741      * }
13742      *
13743      * Foo.prototype.c = 3;
13744      *
13745      * _.toPairsIn(new Foo);
13746      * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
13747      */
13748     var toPairsIn = createToPairs(keysIn);
13749
13750     /**
13751      * An alternative to `_.reduce`; this method transforms `object` to a new
13752      * `accumulator` object which is the result of running each of its own
13753      * enumerable string keyed properties thru `iteratee`, with each invocation
13754      * potentially mutating the `accumulator` object. If `accumulator` is not
13755      * provided, a new object with the same `[[Prototype]]` will be used. The
13756      * iteratee is invoked with four arguments: (accumulator, value, key, object).
13757      * Iteratee functions may exit iteration early by explicitly returning `false`.
13758      *
13759      * @static
13760      * @memberOf _
13761      * @since 1.3.0
13762      * @category Object
13763      * @param {Object} object The object to iterate over.
13764      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13765      * @param {*} [accumulator] The custom accumulator value.
13766      * @returns {*} Returns the accumulated value.
13767      * @example
13768      *
13769      * _.transform([2, 3, 4], function(result, n) {
13770      *   result.push(n *= n);
13771      *   return n % 2 == 0;
13772      * }, []);
13773      * // => [4, 9]
13774      *
13775      * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
13776      *   (result[value] || (result[value] = [])).push(key);
13777      * }, {});
13778      * // => { '1': ['a', 'c'], '2': ['b'] }
13779      */
13780     function transform(object, iteratee, accumulator) {
13781       var isArr = isArray(object),
13782           isArrLike = isArr || isBuffer(object) || isTypedArray(object);
13783
13784       iteratee = getIteratee(iteratee, 4);
13785       if (accumulator == null) {
13786         var Ctor = object && object.constructor;
13787         if (isArrLike) {
13788           accumulator = isArr ? new Ctor : [];
13789         }
13790         else if (isObject(object)) {
13791           accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
13792         }
13793         else {
13794           accumulator = {};
13795         }
13796       }
13797       (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
13798         return iteratee(accumulator, value, index, object);
13799       });
13800       return accumulator;
13801     }
13802
13803     /**
13804      * Removes the property at `path` of `object`.
13805      *
13806      * **Note:** This method mutates `object`.
13807      *
13808      * @static
13809      * @memberOf _
13810      * @since 4.0.0
13811      * @category Object
13812      * @param {Object} object The object to modify.
13813      * @param {Array|string} path The path of the property to unset.
13814      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
13815      * @example
13816      *
13817      * var object = { 'a': [{ 'b': { 'c': 7 } }] };
13818      * _.unset(object, 'a[0].b.c');
13819      * // => true
13820      *
13821      * console.log(object);
13822      * // => { 'a': [{ 'b': {} }] };
13823      *
13824      * _.unset(object, ['a', '0', 'b', 'c']);
13825      * // => true
13826      *
13827      * console.log(object);
13828      * // => { 'a': [{ 'b': {} }] };
13829      */
13830     function unset(object, path) {
13831       return object == null ? true : baseUnset(object, path);
13832     }
13833
13834     /**
13835      * This method is like `_.set` except that accepts `updater` to produce the
13836      * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
13837      * is invoked with one argument: (value).
13838      *
13839      * **Note:** This method mutates `object`.
13840      *
13841      * @static
13842      * @memberOf _
13843      * @since 4.6.0
13844      * @category Object
13845      * @param {Object} object The object to modify.
13846      * @param {Array|string} path The path of the property to set.
13847      * @param {Function} updater The function to produce the updated value.
13848      * @returns {Object} Returns `object`.
13849      * @example
13850      *
13851      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13852      *
13853      * _.update(object, 'a[0].b.c', function(n) { return n * n; });
13854      * console.log(object.a[0].b.c);
13855      * // => 9
13856      *
13857      * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
13858      * console.log(object.x[0].y.z);
13859      * // => 0
13860      */
13861     function update(object, path, updater) {
13862       return object == null ? object : baseUpdate(object, path, castFunction(updater));
13863     }
13864
13865     /**
13866      * This method is like `_.update` except that it accepts `customizer` which is
13867      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13868      * path creation is handled by the method instead. The `customizer` is invoked
13869      * with three arguments: (nsValue, key, nsObject).
13870      *
13871      * **Note:** This method mutates `object`.
13872      *
13873      * @static
13874      * @memberOf _
13875      * @since 4.6.0
13876      * @category Object
13877      * @param {Object} object The object to modify.
13878      * @param {Array|string} path The path of the property to set.
13879      * @param {Function} updater The function to produce the updated value.
13880      * @param {Function} [customizer] The function to customize assigned values.
13881      * @returns {Object} Returns `object`.
13882      * @example
13883      *
13884      * var object = {};
13885      *
13886      * _.updateWith(object, '[0][1]', _.constant('a'), Object);
13887      * // => { '0': { '1': 'a' } }
13888      */
13889     function updateWith(object, path, updater, customizer) {
13890       customizer = typeof customizer == 'function' ? customizer : undefined;
13891       return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
13892     }
13893
13894     /**
13895      * Creates an array of the own enumerable string keyed property values of `object`.
13896      *
13897      * **Note:** Non-object values are coerced to objects.
13898      *
13899      * @static
13900      * @since 0.1.0
13901      * @memberOf _
13902      * @category Object
13903      * @param {Object} object The object to query.
13904      * @returns {Array} Returns the array of property values.
13905      * @example
13906      *
13907      * function Foo() {
13908      *   this.a = 1;
13909      *   this.b = 2;
13910      * }
13911      *
13912      * Foo.prototype.c = 3;
13913      *
13914      * _.values(new Foo);
13915      * // => [1, 2] (iteration order is not guaranteed)
13916      *
13917      * _.values('hi');
13918      * // => ['h', 'i']
13919      */
13920     function values(object) {
13921       return object == null ? [] : baseValues(object, keys(object));
13922     }
13923
13924     /**
13925      * Creates an array of the own and inherited enumerable string keyed property
13926      * values of `object`.
13927      *
13928      * **Note:** Non-object values are coerced to objects.
13929      *
13930      * @static
13931      * @memberOf _
13932      * @since 3.0.0
13933      * @category Object
13934      * @param {Object} object The object to query.
13935      * @returns {Array} Returns the array of property values.
13936      * @example
13937      *
13938      * function Foo() {
13939      *   this.a = 1;
13940      *   this.b = 2;
13941      * }
13942      *
13943      * Foo.prototype.c = 3;
13944      *
13945      * _.valuesIn(new Foo);
13946      * // => [1, 2, 3] (iteration order is not guaranteed)
13947      */
13948     function valuesIn(object) {
13949       return object == null ? [] : baseValues(object, keysIn(object));
13950     }
13951
13952     /*------------------------------------------------------------------------*/
13953
13954     /**
13955      * Clamps `number` within the inclusive `lower` and `upper` bounds.
13956      *
13957      * @static
13958      * @memberOf _
13959      * @since 4.0.0
13960      * @category Number
13961      * @param {number} number The number to clamp.
13962      * @param {number} [lower] The lower bound.
13963      * @param {number} upper The upper bound.
13964      * @returns {number} Returns the clamped number.
13965      * @example
13966      *
13967      * _.clamp(-10, -5, 5);
13968      * // => -5
13969      *
13970      * _.clamp(10, -5, 5);
13971      * // => 5
13972      */
13973     function clamp(number, lower, upper) {
13974       if (upper === undefined) {
13975         upper = lower;
13976         lower = undefined;
13977       }
13978       if (upper !== undefined) {
13979         upper = toNumber(upper);
13980         upper = upper === upper ? upper : 0;
13981       }
13982       if (lower !== undefined) {
13983         lower = toNumber(lower);
13984         lower = lower === lower ? lower : 0;
13985       }
13986       return baseClamp(toNumber(number), lower, upper);
13987     }
13988
13989     /**
13990      * Checks if `n` is between `start` and up to, but not including, `end`. If
13991      * `end` is not specified, it's set to `start` with `start` then set to `0`.
13992      * If `start` is greater than `end` the params are swapped to support
13993      * negative ranges.
13994      *
13995      * @static
13996      * @memberOf _
13997      * @since 3.3.0
13998      * @category Number
13999      * @param {number} number The number to check.
14000      * @param {number} [start=0] The start of the range.
14001      * @param {number} end The end of the range.
14002      * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
14003      * @see _.range, _.rangeRight
14004      * @example
14005      *
14006      * _.inRange(3, 2, 4);
14007      * // => true
14008      *
14009      * _.inRange(4, 8);
14010      * // => true
14011      *
14012      * _.inRange(4, 2);
14013      * // => false
14014      *
14015      * _.inRange(2, 2);
14016      * // => false
14017      *
14018      * _.inRange(1.2, 2);
14019      * // => true
14020      *
14021      * _.inRange(5.2, 4);
14022      * // => false
14023      *
14024      * _.inRange(-3, -2, -6);
14025      * // => true
14026      */
14027     function inRange(number, start, end) {
14028       start = toFinite(start);
14029       if (end === undefined) {
14030         end = start;
14031         start = 0;
14032       } else {
14033         end = toFinite(end);
14034       }
14035       number = toNumber(number);
14036       return baseInRange(number, start, end);
14037     }
14038
14039     /**
14040      * Produces a random number between the inclusive `lower` and `upper` bounds.
14041      * If only one argument is provided a number between `0` and the given number
14042      * is returned. If `floating` is `true`, or either `lower` or `upper` are
14043      * floats, a floating-point number is returned instead of an integer.
14044      *
14045      * **Note:** JavaScript follows the IEEE-754 standard for resolving
14046      * floating-point values which can produce unexpected results.
14047      *
14048      * @static
14049      * @memberOf _
14050      * @since 0.7.0
14051      * @category Number
14052      * @param {number} [lower=0] The lower bound.
14053      * @param {number} [upper=1] The upper bound.
14054      * @param {boolean} [floating] Specify returning a floating-point number.
14055      * @returns {number} Returns the random number.
14056      * @example
14057      *
14058      * _.random(0, 5);
14059      * // => an integer between 0 and 5
14060      *
14061      * _.random(5);
14062      * // => also an integer between 0 and 5
14063      *
14064      * _.random(5, true);
14065      * // => a floating-point number between 0 and 5
14066      *
14067      * _.random(1.2, 5.2);
14068      * // => a floating-point number between 1.2 and 5.2
14069      */
14070     function random(lower, upper, floating) {
14071       if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
14072         upper = floating = undefined;
14073       }
14074       if (floating === undefined) {
14075         if (typeof upper == 'boolean') {
14076           floating = upper;
14077           upper = undefined;
14078         }
14079         else if (typeof lower == 'boolean') {
14080           floating = lower;
14081           lower = undefined;
14082         }
14083       }
14084       if (lower === undefined && upper === undefined) {
14085         lower = 0;
14086         upper = 1;
14087       }
14088       else {
14089         lower = toFinite(lower);
14090         if (upper === undefined) {
14091           upper = lower;
14092           lower = 0;
14093         } else {
14094           upper = toFinite(upper);
14095         }
14096       }
14097       if (lower > upper) {
14098         var temp = lower;
14099         lower = upper;
14100         upper = temp;
14101       }
14102       if (floating || lower % 1 || upper % 1) {
14103         var rand = nativeRandom();
14104         return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
14105       }
14106       return baseRandom(lower, upper);
14107     }
14108
14109     /*------------------------------------------------------------------------*/
14110
14111     /**
14112      * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
14113      *
14114      * @static
14115      * @memberOf _
14116      * @since 3.0.0
14117      * @category String
14118      * @param {string} [string=''] The string to convert.
14119      * @returns {string} Returns the camel cased string.
14120      * @example
14121      *
14122      * _.camelCase('Foo Bar');
14123      * // => 'fooBar'
14124      *
14125      * _.camelCase('--foo-bar--');
14126      * // => 'fooBar'
14127      *
14128      * _.camelCase('__FOO_BAR__');
14129      * // => 'fooBar'
14130      */
14131     var camelCase = createCompounder(function(result, word, index) {
14132       word = word.toLowerCase();
14133       return result + (index ? capitalize(word) : word);
14134     });
14135
14136     /**
14137      * Converts the first character of `string` to upper case and the remaining
14138      * to lower case.
14139      *
14140      * @static
14141      * @memberOf _
14142      * @since 3.0.0
14143      * @category String
14144      * @param {string} [string=''] The string to capitalize.
14145      * @returns {string} Returns the capitalized string.
14146      * @example
14147      *
14148      * _.capitalize('FRED');
14149      * // => 'Fred'
14150      */
14151     function capitalize(string) {
14152       return upperFirst(toString(string).toLowerCase());
14153     }
14154
14155     /**
14156      * Deburrs `string` by converting
14157      * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
14158      * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
14159      * letters to basic Latin letters and removing
14160      * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
14161      *
14162      * @static
14163      * @memberOf _
14164      * @since 3.0.0
14165      * @category String
14166      * @param {string} [string=''] The string to deburr.
14167      * @returns {string} Returns the deburred string.
14168      * @example
14169      *
14170      * _.deburr('déjà vu');
14171      * // => 'deja vu'
14172      */
14173     function deburr(string) {
14174       string = toString(string);
14175       return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
14176     }
14177
14178     /**
14179      * Checks if `string` ends with the given target string.
14180      *
14181      * @static
14182      * @memberOf _
14183      * @since 3.0.0
14184      * @category String
14185      * @param {string} [string=''] The string to inspect.
14186      * @param {string} [target] The string to search for.
14187      * @param {number} [position=string.length] The position to search up to.
14188      * @returns {boolean} Returns `true` if `string` ends with `target`,
14189      *  else `false`.
14190      * @example
14191      *
14192      * _.endsWith('abc', 'c');
14193      * // => true
14194      *
14195      * _.endsWith('abc', 'b');
14196      * // => false
14197      *
14198      * _.endsWith('abc', 'b', 2);
14199      * // => true
14200      */
14201     function endsWith(string, target, position) {
14202       string = toString(string);
14203       target = baseToString(target);
14204
14205       var length = string.length;
14206       position = position === undefined
14207         ? length
14208         : baseClamp(toInteger(position), 0, length);
14209
14210       var end = position;
14211       position -= target.length;
14212       return position >= 0 && string.slice(position, end) == target;
14213     }
14214
14215     /**
14216      * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
14217      * corresponding HTML entities.
14218      *
14219      * **Note:** No other characters are escaped. To escape additional
14220      * characters use a third-party library like [_he_](https://mths.be/he).
14221      *
14222      * Though the ">" character is escaped for symmetry, characters like
14223      * ">" and "/" don't need escaping in HTML and have no special meaning
14224      * unless they're part of a tag or unquoted attribute value. See
14225      * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
14226      * (under "semi-related fun fact") for more details.
14227      *
14228      * When working with HTML you should always
14229      * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
14230      * XSS vectors.
14231      *
14232      * @static
14233      * @since 0.1.0
14234      * @memberOf _
14235      * @category String
14236      * @param {string} [string=''] The string to escape.
14237      * @returns {string} Returns the escaped string.
14238      * @example
14239      *
14240      * _.escape('fred, barney, & pebbles');
14241      * // => 'fred, barney, &amp; pebbles'
14242      */
14243     function escape(string) {
14244       string = toString(string);
14245       return (string && reHasUnescapedHtml.test(string))
14246         ? string.replace(reUnescapedHtml, escapeHtmlChar)
14247         : string;
14248     }
14249
14250     /**
14251      * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
14252      * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
14253      *
14254      * @static
14255      * @memberOf _
14256      * @since 3.0.0
14257      * @category String
14258      * @param {string} [string=''] The string to escape.
14259      * @returns {string} Returns the escaped string.
14260      * @example
14261      *
14262      * _.escapeRegExp('[lodash](https://lodash.com/)');
14263      * // => '\[lodash\]\(https://lodash\.com/\)'
14264      */
14265     function escapeRegExp(string) {
14266       string = toString(string);
14267       return (string && reHasRegExpChar.test(string))
14268         ? string.replace(reRegExpChar, '\\$&')
14269         : string;
14270     }
14271
14272     /**
14273      * Converts `string` to
14274      * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
14275      *
14276      * @static
14277      * @memberOf _
14278      * @since 3.0.0
14279      * @category String
14280      * @param {string} [string=''] The string to convert.
14281      * @returns {string} Returns the kebab cased string.
14282      * @example
14283      *
14284      * _.kebabCase('Foo Bar');
14285      * // => 'foo-bar'
14286      *
14287      * _.kebabCase('fooBar');
14288      * // => 'foo-bar'
14289      *
14290      * _.kebabCase('__FOO_BAR__');
14291      * // => 'foo-bar'
14292      */
14293     var kebabCase = createCompounder(function(result, word, index) {
14294       return result + (index ? '-' : '') + word.toLowerCase();
14295     });
14296
14297     /**
14298      * Converts `string`, as space separated words, to lower case.
14299      *
14300      * @static
14301      * @memberOf _
14302      * @since 4.0.0
14303      * @category String
14304      * @param {string} [string=''] The string to convert.
14305      * @returns {string} Returns the lower cased string.
14306      * @example
14307      *
14308      * _.lowerCase('--Foo-Bar--');
14309      * // => 'foo bar'
14310      *
14311      * _.lowerCase('fooBar');
14312      * // => 'foo bar'
14313      *
14314      * _.lowerCase('__FOO_BAR__');
14315      * // => 'foo bar'
14316      */
14317     var lowerCase = createCompounder(function(result, word, index) {
14318       return result + (index ? ' ' : '') + word.toLowerCase();
14319     });
14320
14321     /**
14322      * Converts the first character of `string` to lower case.
14323      *
14324      * @static
14325      * @memberOf _
14326      * @since 4.0.0
14327      * @category String
14328      * @param {string} [string=''] The string to convert.
14329      * @returns {string} Returns the converted string.
14330      * @example
14331      *
14332      * _.lowerFirst('Fred');
14333      * // => 'fred'
14334      *
14335      * _.lowerFirst('FRED');
14336      * // => 'fRED'
14337      */
14338     var lowerFirst = createCaseFirst('toLowerCase');
14339
14340     /**
14341      * Pads `string` on the left and right sides if it's shorter than `length`.
14342      * Padding characters are truncated if they can't be evenly divided by `length`.
14343      *
14344      * @static
14345      * @memberOf _
14346      * @since 3.0.0
14347      * @category String
14348      * @param {string} [string=''] The string to pad.
14349      * @param {number} [length=0] The padding length.
14350      * @param {string} [chars=' '] The string used as padding.
14351      * @returns {string} Returns the padded string.
14352      * @example
14353      *
14354      * _.pad('abc', 8);
14355      * // => '  abc   '
14356      *
14357      * _.pad('abc', 8, '_-');
14358      * // => '_-abc_-_'
14359      *
14360      * _.pad('abc', 3);
14361      * // => 'abc'
14362      */
14363     function pad(string, length, chars) {
14364       string = toString(string);
14365       length = toInteger(length);
14366
14367       var strLength = length ? stringSize(string) : 0;
14368       if (!length || strLength >= length) {
14369         return string;
14370       }
14371       var mid = (length - strLength) / 2;
14372       return (
14373         createPadding(nativeFloor(mid), chars) +
14374         string +
14375         createPadding(nativeCeil(mid), chars)
14376       );
14377     }
14378
14379     /**
14380      * Pads `string` on the right side if it's shorter than `length`. Padding
14381      * characters are truncated if they exceed `length`.
14382      *
14383      * @static
14384      * @memberOf _
14385      * @since 4.0.0
14386      * @category String
14387      * @param {string} [string=''] The string to pad.
14388      * @param {number} [length=0] The padding length.
14389      * @param {string} [chars=' '] The string used as padding.
14390      * @returns {string} Returns the padded string.
14391      * @example
14392      *
14393      * _.padEnd('abc', 6);
14394      * // => 'abc   '
14395      *
14396      * _.padEnd('abc', 6, '_-');
14397      * // => 'abc_-_'
14398      *
14399      * _.padEnd('abc', 3);
14400      * // => 'abc'
14401      */
14402     function padEnd(string, length, chars) {
14403       string = toString(string);
14404       length = toInteger(length);
14405
14406       var strLength = length ? stringSize(string) : 0;
14407       return (length && strLength < length)
14408         ? (string + createPadding(length - strLength, chars))
14409         : string;
14410     }
14411
14412     /**
14413      * Pads `string` on the left side if it's shorter than `length`. Padding
14414      * characters are truncated if they exceed `length`.
14415      *
14416      * @static
14417      * @memberOf _
14418      * @since 4.0.0
14419      * @category String
14420      * @param {string} [string=''] The string to pad.
14421      * @param {number} [length=0] The padding length.
14422      * @param {string} [chars=' '] The string used as padding.
14423      * @returns {string} Returns the padded string.
14424      * @example
14425      *
14426      * _.padStart('abc', 6);
14427      * // => '   abc'
14428      *
14429      * _.padStart('abc', 6, '_-');
14430      * // => '_-_abc'
14431      *
14432      * _.padStart('abc', 3);
14433      * // => 'abc'
14434      */
14435     function padStart(string, length, chars) {
14436       string = toString(string);
14437       length = toInteger(length);
14438
14439       var strLength = length ? stringSize(string) : 0;
14440       return (length && strLength < length)
14441         ? (createPadding(length - strLength, chars) + string)
14442         : string;
14443     }
14444
14445     /**
14446      * Converts `string` to an integer of the specified radix. If `radix` is
14447      * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
14448      * hexadecimal, in which case a `radix` of `16` is used.
14449      *
14450      * **Note:** This method aligns with the
14451      * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
14452      *
14453      * @static
14454      * @memberOf _
14455      * @since 1.1.0
14456      * @category String
14457      * @param {string} string The string to convert.
14458      * @param {number} [radix=10] The radix to interpret `value` by.
14459      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14460      * @returns {number} Returns the converted integer.
14461      * @example
14462      *
14463      * _.parseInt('08');
14464      * // => 8
14465      *
14466      * _.map(['6', '08', '10'], _.parseInt);
14467      * // => [6, 8, 10]
14468      */
14469     function parseInt(string, radix, guard) {
14470       if (guard || radix == null) {
14471         radix = 0;
14472       } else if (radix) {
14473         radix = +radix;
14474       }
14475       return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
14476     }
14477
14478     /**
14479      * Repeats the given string `n` times.
14480      *
14481      * @static
14482      * @memberOf _
14483      * @since 3.0.0
14484      * @category String
14485      * @param {string} [string=''] The string to repeat.
14486      * @param {number} [n=1] The number of times to repeat the string.
14487      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14488      * @returns {string} Returns the repeated string.
14489      * @example
14490      *
14491      * _.repeat('*', 3);
14492      * // => '***'
14493      *
14494      * _.repeat('abc', 2);
14495      * // => 'abcabc'
14496      *
14497      * _.repeat('abc', 0);
14498      * // => ''
14499      */
14500     function repeat(string, n, guard) {
14501       if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
14502         n = 1;
14503       } else {
14504         n = toInteger(n);
14505       }
14506       return baseRepeat(toString(string), n);
14507     }
14508
14509     /**
14510      * Replaces matches for `pattern` in `string` with `replacement`.
14511      *
14512      * **Note:** This method is based on
14513      * [`String#replace`](https://mdn.io/String/replace).
14514      *
14515      * @static
14516      * @memberOf _
14517      * @since 4.0.0
14518      * @category String
14519      * @param {string} [string=''] The string to modify.
14520      * @param {RegExp|string} pattern The pattern to replace.
14521      * @param {Function|string} replacement The match replacement.
14522      * @returns {string} Returns the modified string.
14523      * @example
14524      *
14525      * _.replace('Hi Fred', 'Fred', 'Barney');
14526      * // => 'Hi Barney'
14527      */
14528     function replace() {
14529       var args = arguments,
14530           string = toString(args[0]);
14531
14532       return args.length < 3 ? string : string.replace(args[1], args[2]);
14533     }
14534
14535     /**
14536      * Converts `string` to
14537      * [snake case](https://en.wikipedia.org/wiki/Snake_case).
14538      *
14539      * @static
14540      * @memberOf _
14541      * @since 3.0.0
14542      * @category String
14543      * @param {string} [string=''] The string to convert.
14544      * @returns {string} Returns the snake cased string.
14545      * @example
14546      *
14547      * _.snakeCase('Foo Bar');
14548      * // => 'foo_bar'
14549      *
14550      * _.snakeCase('fooBar');
14551      * // => 'foo_bar'
14552      *
14553      * _.snakeCase('--FOO-BAR--');
14554      * // => 'foo_bar'
14555      */
14556     var snakeCase = createCompounder(function(result, word, index) {
14557       return result + (index ? '_' : '') + word.toLowerCase();
14558     });
14559
14560     /**
14561      * Splits `string` by `separator`.
14562      *
14563      * **Note:** This method is based on
14564      * [`String#split`](https://mdn.io/String/split).
14565      *
14566      * @static
14567      * @memberOf _
14568      * @since 4.0.0
14569      * @category String
14570      * @param {string} [string=''] The string to split.
14571      * @param {RegExp|string} separator The separator pattern to split by.
14572      * @param {number} [limit] The length to truncate results to.
14573      * @returns {Array} Returns the string segments.
14574      * @example
14575      *
14576      * _.split('a-b-c', '-', 2);
14577      * // => ['a', 'b']
14578      */
14579     function split(string, separator, limit) {
14580       if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
14581         separator = limit = undefined;
14582       }
14583       limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
14584       if (!limit) {
14585         return [];
14586       }
14587       string = toString(string);
14588       if (string && (
14589             typeof separator == 'string' ||
14590             (separator != null && !isRegExp(separator))
14591           )) {
14592         separator = baseToString(separator);
14593         if (!separator && hasUnicode(string)) {
14594           return castSlice(stringToArray(string), 0, limit);
14595         }
14596       }
14597       return string.split(separator, limit);
14598     }
14599
14600     /**
14601      * Converts `string` to
14602      * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
14603      *
14604      * @static
14605      * @memberOf _
14606      * @since 3.1.0
14607      * @category String
14608      * @param {string} [string=''] The string to convert.
14609      * @returns {string} Returns the start cased string.
14610      * @example
14611      *
14612      * _.startCase('--foo-bar--');
14613      * // => 'Foo Bar'
14614      *
14615      * _.startCase('fooBar');
14616      * // => 'Foo Bar'
14617      *
14618      * _.startCase('__FOO_BAR__');
14619      * // => 'FOO BAR'
14620      */
14621     var startCase = createCompounder(function(result, word, index) {
14622       return result + (index ? ' ' : '') + upperFirst(word);
14623     });
14624
14625     /**
14626      * Checks if `string` starts with the given target string.
14627      *
14628      * @static
14629      * @memberOf _
14630      * @since 3.0.0
14631      * @category String
14632      * @param {string} [string=''] The string to inspect.
14633      * @param {string} [target] The string to search for.
14634      * @param {number} [position=0] The position to search from.
14635      * @returns {boolean} Returns `true` if `string` starts with `target`,
14636      *  else `false`.
14637      * @example
14638      *
14639      * _.startsWith('abc', 'a');
14640      * // => true
14641      *
14642      * _.startsWith('abc', 'b');
14643      * // => false
14644      *
14645      * _.startsWith('abc', 'b', 1);
14646      * // => true
14647      */
14648     function startsWith(string, target, position) {
14649       string = toString(string);
14650       position = baseClamp(toInteger(position), 0, string.length);
14651       target = baseToString(target);
14652       return string.slice(position, position + target.length) == target;
14653     }
14654
14655     /**
14656      * Creates a compiled template function that can interpolate data properties
14657      * in "interpolate" delimiters, HTML-escape interpolated data properties in
14658      * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
14659      * properties may be accessed as free variables in the template. If a setting
14660      * object is given, it takes precedence over `_.templateSettings` values.
14661      *
14662      * **Note:** In the development build `_.template` utilizes
14663      * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
14664      * for easier debugging.
14665      *
14666      * For more information on precompiling templates see
14667      * [lodash's custom builds documentation](https://lodash.com/custom-builds).
14668      *
14669      * For more information on Chrome extension sandboxes see
14670      * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
14671      *
14672      * @static
14673      * @since 0.1.0
14674      * @memberOf _
14675      * @category String
14676      * @param {string} [string=''] The template string.
14677      * @param {Object} [options={}] The options object.
14678      * @param {RegExp} [options.escape=_.templateSettings.escape]
14679      *  The HTML "escape" delimiter.
14680      * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
14681      *  The "evaluate" delimiter.
14682      * @param {Object} [options.imports=_.templateSettings.imports]
14683      *  An object to import into the template as free variables.
14684      * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
14685      *  The "interpolate" delimiter.
14686      * @param {string} [options.sourceURL='lodash.templateSources[n]']
14687      *  The sourceURL of the compiled template.
14688      * @param {string} [options.variable='obj']
14689      *  The data object variable name.
14690      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14691      * @returns {Function} Returns the compiled template function.
14692      * @example
14693      *
14694      * // Use the "interpolate" delimiter to create a compiled template.
14695      * var compiled = _.template('hello <%= user %>!');
14696      * compiled({ 'user': 'fred' });
14697      * // => 'hello fred!'
14698      *
14699      * // Use the HTML "escape" delimiter to escape data property values.
14700      * var compiled = _.template('<b><%- value %></b>');
14701      * compiled({ 'value': '<script>' });
14702      * // => '<b>&lt;script&gt;</b>'
14703      *
14704      * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
14705      * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
14706      * compiled({ 'users': ['fred', 'barney'] });
14707      * // => '<li>fred</li><li>barney</li>'
14708      *
14709      * // Use the internal `print` function in "evaluate" delimiters.
14710      * var compiled = _.template('<% print("hello " + user); %>!');
14711      * compiled({ 'user': 'barney' });
14712      * // => 'hello barney!'
14713      *
14714      * // Use the ES template literal delimiter as an "interpolate" delimiter.
14715      * // Disable support by replacing the "interpolate" delimiter.
14716      * var compiled = _.template('hello ${ user }!');
14717      * compiled({ 'user': 'pebbles' });
14718      * // => 'hello pebbles!'
14719      *
14720      * // Use backslashes to treat delimiters as plain text.
14721      * var compiled = _.template('<%= "\\<%- value %\\>" %>');
14722      * compiled({ 'value': 'ignored' });
14723      * // => '<%- value %>'
14724      *
14725      * // Use the `imports` option to import `jQuery` as `jq`.
14726      * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
14727      * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
14728      * compiled({ 'users': ['fred', 'barney'] });
14729      * // => '<li>fred</li><li>barney</li>'
14730      *
14731      * // Use the `sourceURL` option to specify a custom sourceURL for the template.
14732      * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
14733      * compiled(data);
14734      * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
14735      *
14736      * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
14737      * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
14738      * compiled.source;
14739      * // => function(data) {
14740      * //   var __t, __p = '';
14741      * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
14742      * //   return __p;
14743      * // }
14744      *
14745      * // Use custom template delimiters.
14746      * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
14747      * var compiled = _.template('hello {{ user }}!');
14748      * compiled({ 'user': 'mustache' });
14749      * // => 'hello mustache!'
14750      *
14751      * // Use the `source` property to inline compiled templates for meaningful
14752      * // line numbers in error messages and stack traces.
14753      * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
14754      *   var JST = {\
14755      *     "main": ' + _.template(mainText).source + '\
14756      *   };\
14757      * ');
14758      */
14759     function template(string, options, guard) {
14760       // Based on John Resig's `tmpl` implementation
14761       // (http://ejohn.org/blog/javascript-micro-templating/)
14762       // and Laura Doktorova's doT.js (https://github.com/olado/doT).
14763       var settings = lodash.templateSettings;
14764
14765       if (guard && isIterateeCall(string, options, guard)) {
14766         options = undefined;
14767       }
14768       string = toString(string);
14769       options = assignInWith({}, options, settings, assignInDefaults);
14770
14771       var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
14772           importsKeys = keys(imports),
14773           importsValues = baseValues(imports, importsKeys);
14774
14775       var isEscaping,
14776           isEvaluating,
14777           index = 0,
14778           interpolate = options.interpolate || reNoMatch,
14779           source = "__p += '";
14780
14781       // Compile the regexp to match each delimiter.
14782       var reDelimiters = RegExp(
14783         (options.escape || reNoMatch).source + '|' +
14784         interpolate.source + '|' +
14785         (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
14786         (options.evaluate || reNoMatch).source + '|$'
14787       , 'g');
14788
14789       // Use a sourceURL for easier debugging.
14790       var sourceURL = '//# sourceURL=' +
14791         ('sourceURL' in options
14792           ? options.sourceURL
14793           : ('lodash.templateSources[' + (++templateCounter) + ']')
14794         ) + '\n';
14795
14796       string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
14797         interpolateValue || (interpolateValue = esTemplateValue);
14798
14799         // Escape characters that can't be included in string literals.
14800         source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
14801
14802         // Replace delimiters with snippets.
14803         if (escapeValue) {
14804           isEscaping = true;
14805           source += "' +\n__e(" + escapeValue + ") +\n'";
14806         }
14807         if (evaluateValue) {
14808           isEvaluating = true;
14809           source += "';\n" + evaluateValue + ";\n__p += '";
14810         }
14811         if (interpolateValue) {
14812           source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
14813         }
14814         index = offset + match.length;
14815
14816         // The JS engine embedded in Adobe products needs `match` returned in
14817         // order to produce the correct `offset` value.
14818         return match;
14819       });
14820
14821       source += "';\n";
14822
14823       // If `variable` is not specified wrap a with-statement around the generated
14824       // code to add the data object to the top of the scope chain.
14825       var variable = options.variable;
14826       if (!variable) {
14827         source = 'with (obj) {\n' + source + '\n}\n';
14828       }
14829       // Cleanup code by stripping empty strings.
14830       source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
14831         .replace(reEmptyStringMiddle, '$1')
14832         .replace(reEmptyStringTrailing, '$1;');
14833
14834       // Frame code as the function body.
14835       source = 'function(' + (variable || 'obj') + ') {\n' +
14836         (variable
14837           ? ''
14838           : 'obj || (obj = {});\n'
14839         ) +
14840         "var __t, __p = ''" +
14841         (isEscaping
14842            ? ', __e = _.escape'
14843            : ''
14844         ) +
14845         (isEvaluating
14846           ? ', __j = Array.prototype.join;\n' +
14847             "function print() { __p += __j.call(arguments, '') }\n"
14848           : ';\n'
14849         ) +
14850         source +
14851         'return __p\n}';
14852
14853       var result = attempt(function() {
14854         return Function(importsKeys, sourceURL + 'return ' + source)
14855           .apply(undefined, importsValues);
14856       });
14857
14858       // Provide the compiled function's source by its `toString` method or
14859       // the `source` property as a convenience for inlining compiled templates.
14860       result.source = source;
14861       if (isError(result)) {
14862         throw result;
14863       }
14864       return result;
14865     }
14866
14867     /**
14868      * Converts `string`, as a whole, to lower case just like
14869      * [String#toLowerCase](https://mdn.io/toLowerCase).
14870      *
14871      * @static
14872      * @memberOf _
14873      * @since 4.0.0
14874      * @category String
14875      * @param {string} [string=''] The string to convert.
14876      * @returns {string} Returns the lower cased string.
14877      * @example
14878      *
14879      * _.toLower('--Foo-Bar--');
14880      * // => '--foo-bar--'
14881      *
14882      * _.toLower('fooBar');
14883      * // => 'foobar'
14884      *
14885      * _.toLower('__FOO_BAR__');
14886      * // => '__foo_bar__'
14887      */
14888     function toLower(value) {
14889       return toString(value).toLowerCase();
14890     }
14891
14892     /**
14893      * Converts `string`, as a whole, to upper case just like
14894      * [String#toUpperCase](https://mdn.io/toUpperCase).
14895      *
14896      * @static
14897      * @memberOf _
14898      * @since 4.0.0
14899      * @category String
14900      * @param {string} [string=''] The string to convert.
14901      * @returns {string} Returns the upper cased string.
14902      * @example
14903      *
14904      * _.toUpper('--foo-bar--');
14905      * // => '--FOO-BAR--'
14906      *
14907      * _.toUpper('fooBar');
14908      * // => 'FOOBAR'
14909      *
14910      * _.toUpper('__foo_bar__');
14911      * // => '__FOO_BAR__'
14912      */
14913     function toUpper(value) {
14914       return toString(value).toUpperCase();
14915     }
14916
14917     /**
14918      * Removes leading and trailing whitespace or specified characters from `string`.
14919      *
14920      * @static
14921      * @memberOf _
14922      * @since 3.0.0
14923      * @category String
14924      * @param {string} [string=''] The string to trim.
14925      * @param {string} [chars=whitespace] The characters to trim.
14926      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14927      * @returns {string} Returns the trimmed string.
14928      * @example
14929      *
14930      * _.trim('  abc  ');
14931      * // => 'abc'
14932      *
14933      * _.trim('-_-abc-_-', '_-');
14934      * // => 'abc'
14935      *
14936      * _.map(['  foo  ', '  bar  '], _.trim);
14937      * // => ['foo', 'bar']
14938      */
14939     function trim(string, chars, guard) {
14940       string = toString(string);
14941       if (string && (guard || chars === undefined)) {
14942         return string.replace(reTrim, '');
14943       }
14944       if (!string || !(chars = baseToString(chars))) {
14945         return string;
14946       }
14947       var strSymbols = stringToArray(string),
14948           chrSymbols = stringToArray(chars),
14949           start = charsStartIndex(strSymbols, chrSymbols),
14950           end = charsEndIndex(strSymbols, chrSymbols) + 1;
14951
14952       return castSlice(strSymbols, start, end).join('');
14953     }
14954
14955     /**
14956      * Removes trailing whitespace or specified characters from `string`.
14957      *
14958      * @static
14959      * @memberOf _
14960      * @since 4.0.0
14961      * @category String
14962      * @param {string} [string=''] The string to trim.
14963      * @param {string} [chars=whitespace] The characters to trim.
14964      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14965      * @returns {string} Returns the trimmed string.
14966      * @example
14967      *
14968      * _.trimEnd('  abc  ');
14969      * // => '  abc'
14970      *
14971      * _.trimEnd('-_-abc-_-', '_-');
14972      * // => '-_-abc'
14973      */
14974     function trimEnd(string, chars, guard) {
14975       string = toString(string);
14976       if (string && (guard || chars === undefined)) {
14977         return string.replace(reTrimEnd, '');
14978       }
14979       if (!string || !(chars = baseToString(chars))) {
14980         return string;
14981       }
14982       var strSymbols = stringToArray(string),
14983           end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
14984
14985       return castSlice(strSymbols, 0, end).join('');
14986     }
14987
14988     /**
14989      * Removes leading whitespace or specified characters from `string`.
14990      *
14991      * @static
14992      * @memberOf _
14993      * @since 4.0.0
14994      * @category String
14995      * @param {string} [string=''] The string to trim.
14996      * @param {string} [chars=whitespace] The characters to trim.
14997      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14998      * @returns {string} Returns the trimmed string.
14999      * @example
15000      *
15001      * _.trimStart('  abc  ');
15002      * // => 'abc  '
15003      *
15004      * _.trimStart('-_-abc-_-', '_-');
15005      * // => 'abc-_-'
15006      */
15007     function trimStart(string, chars, guard) {
15008       string = toString(string);
15009       if (string && (guard || chars === undefined)) {
15010         return string.replace(reTrimStart, '');
15011       }
15012       if (!string || !(chars = baseToString(chars))) {
15013         return string;
15014       }
15015       var strSymbols = stringToArray(string),
15016           start = charsStartIndex(strSymbols, stringToArray(chars));
15017
15018       return castSlice(strSymbols, start).join('');
15019     }
15020
15021     /**
15022      * Truncates `string` if it's longer than the given maximum string length.
15023      * The last characters of the truncated string are replaced with the omission
15024      * string which defaults to "...".
15025      *
15026      * @static
15027      * @memberOf _
15028      * @since 4.0.0
15029      * @category String
15030      * @param {string} [string=''] The string to truncate.
15031      * @param {Object} [options={}] The options object.
15032      * @param {number} [options.length=30] The maximum string length.
15033      * @param {string} [options.omission='...'] The string to indicate text is omitted.
15034      * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
15035      * @returns {string} Returns the truncated string.
15036      * @example
15037      *
15038      * _.truncate('hi-diddly-ho there, neighborino');
15039      * // => 'hi-diddly-ho there, neighbo...'
15040      *
15041      * _.truncate('hi-diddly-ho there, neighborino', {
15042      *   'length': 24,
15043      *   'separator': ' '
15044      * });
15045      * // => 'hi-diddly-ho there,...'
15046      *
15047      * _.truncate('hi-diddly-ho there, neighborino', {
15048      *   'length': 24,
15049      *   'separator': /,? +/
15050      * });
15051      * // => 'hi-diddly-ho there...'
15052      *
15053      * _.truncate('hi-diddly-ho there, neighborino', {
15054      *   'omission': ' [...]'
15055      * });
15056      * // => 'hi-diddly-ho there, neig [...]'
15057      */
15058     function truncate(string, options) {
15059       var length = DEFAULT_TRUNC_LENGTH,
15060           omission = DEFAULT_TRUNC_OMISSION;
15061
15062       if (isObject(options)) {
15063         var separator = 'separator' in options ? options.separator : separator;
15064         length = 'length' in options ? toInteger(options.length) : length;
15065         omission = 'omission' in options ? baseToString(options.omission) : omission;
15066       }
15067       string = toString(string);
15068
15069       var strLength = string.length;
15070       if (hasUnicode(string)) {
15071         var strSymbols = stringToArray(string);
15072         strLength = strSymbols.length;
15073       }
15074       if (length >= strLength) {
15075         return string;
15076       }
15077       var end = length - stringSize(omission);
15078       if (end < 1) {
15079         return omission;
15080       }
15081       var result = strSymbols
15082         ? castSlice(strSymbols, 0, end).join('')
15083         : string.slice(0, end);
15084
15085       if (separator === undefined) {
15086         return result + omission;
15087       }
15088       if (strSymbols) {
15089         end += (result.length - end);
15090       }
15091       if (isRegExp(separator)) {
15092         if (string.slice(end).search(separator)) {
15093           var match,
15094               substring = result;
15095
15096           if (!separator.global) {
15097             separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
15098           }
15099           separator.lastIndex = 0;
15100           while ((match = separator.exec(substring))) {
15101             var newEnd = match.index;
15102           }
15103           result = result.slice(0, newEnd === undefined ? end : newEnd);
15104         }
15105       } else if (string.indexOf(baseToString(separator), end) != end) {
15106         var index = result.lastIndexOf(separator);
15107         if (index > -1) {
15108           result = result.slice(0, index);
15109         }
15110       }
15111       return result + omission;
15112     }
15113
15114     /**
15115      * The inverse of `_.escape`; this method converts the HTML entities
15116      * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
15117      * their corresponding characters.
15118      *
15119      * **Note:** No other HTML entities are unescaped. To unescape additional
15120      * HTML entities use a third-party library like [_he_](https://mths.be/he).
15121      *
15122      * @static
15123      * @memberOf _
15124      * @since 0.6.0
15125      * @category String
15126      * @param {string} [string=''] The string to unescape.
15127      * @returns {string} Returns the unescaped string.
15128      * @example
15129      *
15130      * _.unescape('fred, barney, &amp; pebbles');
15131      * // => 'fred, barney, & pebbles'
15132      */
15133     function unescape(string) {
15134       string = toString(string);
15135       return (string && reHasEscapedHtml.test(string))
15136         ? string.replace(reEscapedHtml, unescapeHtmlChar)
15137         : string;
15138     }
15139
15140     /**
15141      * Converts `string`, as space separated words, to upper case.
15142      *
15143      * @static
15144      * @memberOf _
15145      * @since 4.0.0
15146      * @category String
15147      * @param {string} [string=''] The string to convert.
15148      * @returns {string} Returns the upper cased string.
15149      * @example
15150      *
15151      * _.upperCase('--foo-bar');
15152      * // => 'FOO BAR'
15153      *
15154      * _.upperCase('fooBar');
15155      * // => 'FOO BAR'
15156      *
15157      * _.upperCase('__foo_bar__');
15158      * // => 'FOO BAR'
15159      */
15160     var upperCase = createCompounder(function(result, word, index) {
15161       return result + (index ? ' ' : '') + word.toUpperCase();
15162     });
15163
15164     /**
15165      * Converts the first character of `string` to upper case.
15166      *
15167      * @static
15168      * @memberOf _
15169      * @since 4.0.0
15170      * @category String
15171      * @param {string} [string=''] The string to convert.
15172      * @returns {string} Returns the converted string.
15173      * @example
15174      *
15175      * _.upperFirst('fred');
15176      * // => 'Fred'
15177      *
15178      * _.upperFirst('FRED');
15179      * // => 'FRED'
15180      */
15181     var upperFirst = createCaseFirst('toUpperCase');
15182
15183     /**
15184      * Splits `string` into an array of its words.
15185      *
15186      * @static
15187      * @memberOf _
15188      * @since 3.0.0
15189      * @category String
15190      * @param {string} [string=''] The string to inspect.
15191      * @param {RegExp|string} [pattern] The pattern to match words.
15192      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15193      * @returns {Array} Returns the words of `string`.
15194      * @example
15195      *
15196      * _.words('fred, barney, & pebbles');
15197      * // => ['fred', 'barney', 'pebbles']
15198      *
15199      * _.words('fred, barney, & pebbles', /[^, ]+/g);
15200      * // => ['fred', 'barney', '&', 'pebbles']
15201      */
15202     function words(string, pattern, guard) {
15203       string = toString(string);
15204       pattern = guard ? undefined : pattern;
15205
15206       if (pattern === undefined) {
15207         return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
15208       }
15209       return string.match(pattern) || [];
15210     }
15211
15212     /*------------------------------------------------------------------------*/
15213
15214     /**
15215      * Attempts to invoke `func`, returning either the result or the caught error
15216      * object. Any additional arguments are provided to `func` when it's invoked.
15217      *
15218      * @static
15219      * @memberOf _
15220      * @since 3.0.0
15221      * @category Util
15222      * @param {Function} func The function to attempt.
15223      * @param {...*} [args] The arguments to invoke `func` with.
15224      * @returns {*} Returns the `func` result or error object.
15225      * @example
15226      *
15227      * // Avoid throwing errors for invalid selectors.
15228      * var elements = _.attempt(function(selector) {
15229      *   return document.querySelectorAll(selector);
15230      * }, '>_>');
15231      *
15232      * if (_.isError(elements)) {
15233      *   elements = [];
15234      * }
15235      */
15236     var attempt = baseRest(function(func, args) {
15237       try {
15238         return apply(func, undefined, args);
15239       } catch (e) {
15240         return isError(e) ? e : new Error(e);
15241       }
15242     });
15243
15244     /**
15245      * Binds methods of an object to the object itself, overwriting the existing
15246      * method.
15247      *
15248      * **Note:** This method doesn't set the "length" property of bound functions.
15249      *
15250      * @static
15251      * @since 0.1.0
15252      * @memberOf _
15253      * @category Util
15254      * @param {Object} object The object to bind and assign the bound methods to.
15255      * @param {...(string|string[])} methodNames The object method names to bind.
15256      * @returns {Object} Returns `object`.
15257      * @example
15258      *
15259      * var view = {
15260      *   'label': 'docs',
15261      *   'click': function() {
15262      *     console.log('clicked ' + this.label);
15263      *   }
15264      * };
15265      *
15266      * _.bindAll(view, ['click']);
15267      * jQuery(element).on('click', view.click);
15268      * // => Logs 'clicked docs' when clicked.
15269      */
15270     var bindAll = flatRest(function(object, methodNames) {
15271       arrayEach(methodNames, function(key) {
15272         key = toKey(key);
15273         baseAssignValue(object, key, bind(object[key], object));
15274       });
15275       return object;
15276     });
15277
15278     /**
15279      * Creates a function that iterates over `pairs` and invokes the corresponding
15280      * function of the first predicate to return truthy. The predicate-function
15281      * pairs are invoked with the `this` binding and arguments of the created
15282      * function.
15283      *
15284      * @static
15285      * @memberOf _
15286      * @since 4.0.0
15287      * @category Util
15288      * @param {Array} pairs The predicate-function pairs.
15289      * @returns {Function} Returns the new composite function.
15290      * @example
15291      *
15292      * var func = _.cond([
15293      *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
15294      *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
15295      *   [_.stubTrue,                      _.constant('no match')]
15296      * ]);
15297      *
15298      * func({ 'a': 1, 'b': 2 });
15299      * // => 'matches A'
15300      *
15301      * func({ 'a': 0, 'b': 1 });
15302      * // => 'matches B'
15303      *
15304      * func({ 'a': '1', 'b': '2' });
15305      * // => 'no match'
15306      */
15307     function cond(pairs) {
15308       var length = pairs == null ? 0 : pairs.length,
15309           toIteratee = getIteratee();
15310
15311       pairs = !length ? [] : arrayMap(pairs, function(pair) {
15312         if (typeof pair[1] != 'function') {
15313           throw new TypeError(FUNC_ERROR_TEXT);
15314         }
15315         return [toIteratee(pair[0]), pair[1]];
15316       });
15317
15318       return baseRest(function(args) {
15319         var index = -1;
15320         while (++index < length) {
15321           var pair = pairs[index];
15322           if (apply(pair[0], this, args)) {
15323             return apply(pair[1], this, args);
15324           }
15325         }
15326       });
15327     }
15328
15329     /**
15330      * Creates a function that invokes the predicate properties of `source` with
15331      * the corresponding property values of a given object, returning `true` if
15332      * all predicates return truthy, else `false`.
15333      *
15334      * **Note:** The created function is equivalent to `_.conformsTo` with
15335      * `source` partially applied.
15336      *
15337      * @static
15338      * @memberOf _
15339      * @since 4.0.0
15340      * @category Util
15341      * @param {Object} source The object of property predicates to conform to.
15342      * @returns {Function} Returns the new spec function.
15343      * @example
15344      *
15345      * var objects = [
15346      *   { 'a': 2, 'b': 1 },
15347      *   { 'a': 1, 'b': 2 }
15348      * ];
15349      *
15350      * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
15351      * // => [{ 'a': 1, 'b': 2 }]
15352      */
15353     function conforms(source) {
15354       return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
15355     }
15356
15357     /**
15358      * Creates a function that returns `value`.
15359      *
15360      * @static
15361      * @memberOf _
15362      * @since 2.4.0
15363      * @category Util
15364      * @param {*} value The value to return from the new function.
15365      * @returns {Function} Returns the new constant function.
15366      * @example
15367      *
15368      * var objects = _.times(2, _.constant({ 'a': 1 }));
15369      *
15370      * console.log(objects);
15371      * // => [{ 'a': 1 }, { 'a': 1 }]
15372      *
15373      * console.log(objects[0] === objects[1]);
15374      * // => true
15375      */
15376     function constant(value) {
15377       return function() {
15378         return value;
15379       };
15380     }
15381
15382     /**
15383      * Checks `value` to determine whether a default value should be returned in
15384      * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
15385      * or `undefined`.
15386      *
15387      * @static
15388      * @memberOf _
15389      * @since 4.14.0
15390      * @category Util
15391      * @param {*} value The value to check.
15392      * @param {*} defaultValue The default value.
15393      * @returns {*} Returns the resolved value.
15394      * @example
15395      *
15396      * _.defaultTo(1, 10);
15397      * // => 1
15398      *
15399      * _.defaultTo(undefined, 10);
15400      * // => 10
15401      */
15402     function defaultTo(value, defaultValue) {
15403       return (value == null || value !== value) ? defaultValue : value;
15404     }
15405
15406     /**
15407      * Creates a function that returns the result of invoking the given functions
15408      * with the `this` binding of the created function, where each successive
15409      * invocation is supplied the return value of the previous.
15410      *
15411      * @static
15412      * @memberOf _
15413      * @since 3.0.0
15414      * @category Util
15415      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15416      * @returns {Function} Returns the new composite function.
15417      * @see _.flowRight
15418      * @example
15419      *
15420      * function square(n) {
15421      *   return n * n;
15422      * }
15423      *
15424      * var addSquare = _.flow([_.add, square]);
15425      * addSquare(1, 2);
15426      * // => 9
15427      */
15428     var flow = createFlow();
15429
15430     /**
15431      * This method is like `_.flow` except that it creates a function that
15432      * invokes the given functions from right to left.
15433      *
15434      * @static
15435      * @since 3.0.0
15436      * @memberOf _
15437      * @category Util
15438      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15439      * @returns {Function} Returns the new composite function.
15440      * @see _.flow
15441      * @example
15442      *
15443      * function square(n) {
15444      *   return n * n;
15445      * }
15446      *
15447      * var addSquare = _.flowRight([square, _.add]);
15448      * addSquare(1, 2);
15449      * // => 9
15450      */
15451     var flowRight = createFlow(true);
15452
15453     /**
15454      * This method returns the first argument it receives.
15455      *
15456      * @static
15457      * @since 0.1.0
15458      * @memberOf _
15459      * @category Util
15460      * @param {*} value Any value.
15461      * @returns {*} Returns `value`.
15462      * @example
15463      *
15464      * var object = { 'a': 1 };
15465      *
15466      * console.log(_.identity(object) === object);
15467      * // => true
15468      */
15469     function identity(value) {
15470       return value;
15471     }
15472
15473     /**
15474      * Creates a function that invokes `func` with the arguments of the created
15475      * function. If `func` is a property name, the created function returns the
15476      * property value for a given element. If `func` is an array or object, the
15477      * created function returns `true` for elements that contain the equivalent
15478      * source properties, otherwise it returns `false`.
15479      *
15480      * @static
15481      * @since 4.0.0
15482      * @memberOf _
15483      * @category Util
15484      * @param {*} [func=_.identity] The value to convert to a callback.
15485      * @returns {Function} Returns the callback.
15486      * @example
15487      *
15488      * var users = [
15489      *   { 'user': 'barney', 'age': 36, 'active': true },
15490      *   { 'user': 'fred',   'age': 40, 'active': false }
15491      * ];
15492      *
15493      * // The `_.matches` iteratee shorthand.
15494      * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
15495      * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
15496      *
15497      * // The `_.matchesProperty` iteratee shorthand.
15498      * _.filter(users, _.iteratee(['user', 'fred']));
15499      * // => [{ 'user': 'fred', 'age': 40 }]
15500      *
15501      * // The `_.property` iteratee shorthand.
15502      * _.map(users, _.iteratee('user'));
15503      * // => ['barney', 'fred']
15504      *
15505      * // Create custom iteratee shorthands.
15506      * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
15507      *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
15508      *     return func.test(string);
15509      *   };
15510      * });
15511      *
15512      * _.filter(['abc', 'def'], /ef/);
15513      * // => ['def']
15514      */
15515     function iteratee(func) {
15516       return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
15517     }
15518
15519     /**
15520      * Creates a function that performs a partial deep comparison between a given
15521      * object and `source`, returning `true` if the given object has equivalent
15522      * property values, else `false`.
15523      *
15524      * **Note:** The created function is equivalent to `_.isMatch` with `source`
15525      * partially applied.
15526      *
15527      * Partial comparisons will match empty array and empty object `source`
15528      * values against any array or object value, respectively. See `_.isEqual`
15529      * for a list of supported value comparisons.
15530      *
15531      * @static
15532      * @memberOf _
15533      * @since 3.0.0
15534      * @category Util
15535      * @param {Object} source The object of property values to match.
15536      * @returns {Function} Returns the new spec function.
15537      * @example
15538      *
15539      * var objects = [
15540      *   { 'a': 1, 'b': 2, 'c': 3 },
15541      *   { 'a': 4, 'b': 5, 'c': 6 }
15542      * ];
15543      *
15544      * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
15545      * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
15546      */
15547     function matches(source) {
15548       return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
15549     }
15550
15551     /**
15552      * Creates a function that performs a partial deep comparison between the
15553      * value at `path` of a given object to `srcValue`, returning `true` if the
15554      * object value is equivalent, else `false`.
15555      *
15556      * **Note:** Partial comparisons will match empty array and empty object
15557      * `srcValue` values against any array or object value, respectively. See
15558      * `_.isEqual` for a list of supported value comparisons.
15559      *
15560      * @static
15561      * @memberOf _
15562      * @since 3.2.0
15563      * @category Util
15564      * @param {Array|string} path The path of the property to get.
15565      * @param {*} srcValue The value to match.
15566      * @returns {Function} Returns the new spec function.
15567      * @example
15568      *
15569      * var objects = [
15570      *   { 'a': 1, 'b': 2, 'c': 3 },
15571      *   { 'a': 4, 'b': 5, 'c': 6 }
15572      * ];
15573      *
15574      * _.find(objects, _.matchesProperty('a', 4));
15575      * // => { 'a': 4, 'b': 5, 'c': 6 }
15576      */
15577     function matchesProperty(path, srcValue) {
15578       return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
15579     }
15580
15581     /**
15582      * Creates a function that invokes the method at `path` of a given object.
15583      * Any additional arguments are provided to the invoked method.
15584      *
15585      * @static
15586      * @memberOf _
15587      * @since 3.7.0
15588      * @category Util
15589      * @param {Array|string} path The path of the method to invoke.
15590      * @param {...*} [args] The arguments to invoke the method with.
15591      * @returns {Function} Returns the new invoker function.
15592      * @example
15593      *
15594      * var objects = [
15595      *   { 'a': { 'b': _.constant(2) } },
15596      *   { 'a': { 'b': _.constant(1) } }
15597      * ];
15598      *
15599      * _.map(objects, _.method('a.b'));
15600      * // => [2, 1]
15601      *
15602      * _.map(objects, _.method(['a', 'b']));
15603      * // => [2, 1]
15604      */
15605     var method = baseRest(function(path, args) {
15606       return function(object) {
15607         return baseInvoke(object, path, args);
15608       };
15609     });
15610
15611     /**
15612      * The opposite of `_.method`; this method creates a function that invokes
15613      * the method at a given path of `object`. Any additional arguments are
15614      * provided to the invoked method.
15615      *
15616      * @static
15617      * @memberOf _
15618      * @since 3.7.0
15619      * @category Util
15620      * @param {Object} object The object to query.
15621      * @param {...*} [args] The arguments to invoke the method with.
15622      * @returns {Function} Returns the new invoker function.
15623      * @example
15624      *
15625      * var array = _.times(3, _.constant),
15626      *     object = { 'a': array, 'b': array, 'c': array };
15627      *
15628      * _.map(['a[2]', 'c[0]'], _.methodOf(object));
15629      * // => [2, 0]
15630      *
15631      * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
15632      * // => [2, 0]
15633      */
15634     var methodOf = baseRest(function(object, args) {
15635       return function(path) {
15636         return baseInvoke(object, path, args);
15637       };
15638     });
15639
15640     /**
15641      * Adds all own enumerable string keyed function properties of a source
15642      * object to the destination object. If `object` is a function, then methods
15643      * are added to its prototype as well.
15644      *
15645      * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
15646      * avoid conflicts caused by modifying the original.
15647      *
15648      * @static
15649      * @since 0.1.0
15650      * @memberOf _
15651      * @category Util
15652      * @param {Function|Object} [object=lodash] The destination object.
15653      * @param {Object} source The object of functions to add.
15654      * @param {Object} [options={}] The options object.
15655      * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
15656      * @returns {Function|Object} Returns `object`.
15657      * @example
15658      *
15659      * function vowels(string) {
15660      *   return _.filter(string, function(v) {
15661      *     return /[aeiou]/i.test(v);
15662      *   });
15663      * }
15664      *
15665      * _.mixin({ 'vowels': vowels });
15666      * _.vowels('fred');
15667      * // => ['e']
15668      *
15669      * _('fred').vowels().value();
15670      * // => ['e']
15671      *
15672      * _.mixin({ 'vowels': vowels }, { 'chain': false });
15673      * _('fred').vowels();
15674      * // => ['e']
15675      */
15676     function mixin(object, source, options) {
15677       var props = keys(source),
15678           methodNames = baseFunctions(source, props);
15679
15680       if (options == null &&
15681           !(isObject(source) && (methodNames.length || !props.length))) {
15682         options = source;
15683         source = object;
15684         object = this;
15685         methodNames = baseFunctions(source, keys(source));
15686       }
15687       var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
15688           isFunc = isFunction(object);
15689
15690       arrayEach(methodNames, function(methodName) {
15691         var func = source[methodName];
15692         object[methodName] = func;
15693         if (isFunc) {
15694           object.prototype[methodName] = function() {
15695             var chainAll = this.__chain__;
15696             if (chain || chainAll) {
15697               var result = object(this.__wrapped__),
15698                   actions = result.__actions__ = copyArray(this.__actions__);
15699
15700               actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
15701               result.__chain__ = chainAll;
15702               return result;
15703             }
15704             return func.apply(object, arrayPush([this.value()], arguments));
15705           };
15706         }
15707       });
15708
15709       return object;
15710     }
15711
15712     /**
15713      * Reverts the `_` variable to its previous value and returns a reference to
15714      * the `lodash` function.
15715      *
15716      * @static
15717      * @since 0.1.0
15718      * @memberOf _
15719      * @category Util
15720      * @returns {Function} Returns the `lodash` function.
15721      * @example
15722      *
15723      * var lodash = _.noConflict();
15724      */
15725     function noConflict() {
15726       if (root._ === this) {
15727         root._ = oldDash;
15728       }
15729       return this;
15730     }
15731
15732     /**
15733      * This method returns `undefined`.
15734      *
15735      * @static
15736      * @memberOf _
15737      * @since 2.3.0
15738      * @category Util
15739      * @example
15740      *
15741      * _.times(2, _.noop);
15742      * // => [undefined, undefined]
15743      */
15744     function noop() {
15745       // No operation performed.
15746     }
15747
15748     /**
15749      * Creates a function that gets the argument at index `n`. If `n` is negative,
15750      * the nth argument from the end is returned.
15751      *
15752      * @static
15753      * @memberOf _
15754      * @since 4.0.0
15755      * @category Util
15756      * @param {number} [n=0] The index of the argument to return.
15757      * @returns {Function} Returns the new pass-thru function.
15758      * @example
15759      *
15760      * var func = _.nthArg(1);
15761      * func('a', 'b', 'c', 'd');
15762      * // => 'b'
15763      *
15764      * var func = _.nthArg(-2);
15765      * func('a', 'b', 'c', 'd');
15766      * // => 'c'
15767      */
15768     function nthArg(n) {
15769       n = toInteger(n);
15770       return baseRest(function(args) {
15771         return baseNth(args, n);
15772       });
15773     }
15774
15775     /**
15776      * Creates a function that invokes `iteratees` with the arguments it receives
15777      * and returns their results.
15778      *
15779      * @static
15780      * @memberOf _
15781      * @since 4.0.0
15782      * @category Util
15783      * @param {...(Function|Function[])} [iteratees=[_.identity]]
15784      *  The iteratees to invoke.
15785      * @returns {Function} Returns the new function.
15786      * @example
15787      *
15788      * var func = _.over([Math.max, Math.min]);
15789      *
15790      * func(1, 2, 3, 4);
15791      * // => [4, 1]
15792      */
15793     var over = createOver(arrayMap);
15794
15795     /**
15796      * Creates a function that checks if **all** of the `predicates` return
15797      * truthy when invoked with the arguments it receives.
15798      *
15799      * @static
15800      * @memberOf _
15801      * @since 4.0.0
15802      * @category Util
15803      * @param {...(Function|Function[])} [predicates=[_.identity]]
15804      *  The predicates to check.
15805      * @returns {Function} Returns the new function.
15806      * @example
15807      *
15808      * var func = _.overEvery([Boolean, isFinite]);
15809      *
15810      * func('1');
15811      * // => true
15812      *
15813      * func(null);
15814      * // => false
15815      *
15816      * func(NaN);
15817      * // => false
15818      */
15819     var overEvery = createOver(arrayEvery);
15820
15821     /**
15822      * Creates a function that checks if **any** of the `predicates` return
15823      * truthy when invoked with the arguments it receives.
15824      *
15825      * @static
15826      * @memberOf _
15827      * @since 4.0.0
15828      * @category Util
15829      * @param {...(Function|Function[])} [predicates=[_.identity]]
15830      *  The predicates to check.
15831      * @returns {Function} Returns the new function.
15832      * @example
15833      *
15834      * var func = _.overSome([Boolean, isFinite]);
15835      *
15836      * func('1');
15837      * // => true
15838      *
15839      * func(null);
15840      * // => true
15841      *
15842      * func(NaN);
15843      * // => false
15844      */
15845     var overSome = createOver(arraySome);
15846
15847     /**
15848      * Creates a function that returns the value at `path` of a given object.
15849      *
15850      * @static
15851      * @memberOf _
15852      * @since 2.4.0
15853      * @category Util
15854      * @param {Array|string} path The path of the property to get.
15855      * @returns {Function} Returns the new accessor function.
15856      * @example
15857      *
15858      * var objects = [
15859      *   { 'a': { 'b': 2 } },
15860      *   { 'a': { 'b': 1 } }
15861      * ];
15862      *
15863      * _.map(objects, _.property('a.b'));
15864      * // => [2, 1]
15865      *
15866      * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
15867      * // => [1, 2]
15868      */
15869     function property(path) {
15870       return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
15871     }
15872
15873     /**
15874      * The opposite of `_.property`; this method creates a function that returns
15875      * the value at a given path of `object`.
15876      *
15877      * @static
15878      * @memberOf _
15879      * @since 3.0.0
15880      * @category Util
15881      * @param {Object} object The object to query.
15882      * @returns {Function} Returns the new accessor function.
15883      * @example
15884      *
15885      * var array = [0, 1, 2],
15886      *     object = { 'a': array, 'b': array, 'c': array };
15887      *
15888      * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
15889      * // => [2, 0]
15890      *
15891      * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
15892      * // => [2, 0]
15893      */
15894     function propertyOf(object) {
15895       return function(path) {
15896         return object == null ? undefined : baseGet(object, path);
15897       };
15898     }
15899
15900     /**
15901      * Creates an array of numbers (positive and/or negative) progressing from
15902      * `start` up to, but not including, `end`. A step of `-1` is used if a negative
15903      * `start` is specified without an `end` or `step`. If `end` is not specified,
15904      * it's set to `start` with `start` then set to `0`.
15905      *
15906      * **Note:** JavaScript follows the IEEE-754 standard for resolving
15907      * floating-point values which can produce unexpected results.
15908      *
15909      * @static
15910      * @since 0.1.0
15911      * @memberOf _
15912      * @category Util
15913      * @param {number} [start=0] The start of the range.
15914      * @param {number} end The end of the range.
15915      * @param {number} [step=1] The value to increment or decrement by.
15916      * @returns {Array} Returns the range of numbers.
15917      * @see _.inRange, _.rangeRight
15918      * @example
15919      *
15920      * _.range(4);
15921      * // => [0, 1, 2, 3]
15922      *
15923      * _.range(-4);
15924      * // => [0, -1, -2, -3]
15925      *
15926      * _.range(1, 5);
15927      * // => [1, 2, 3, 4]
15928      *
15929      * _.range(0, 20, 5);
15930      * // => [0, 5, 10, 15]
15931      *
15932      * _.range(0, -4, -1);
15933      * // => [0, -1, -2, -3]
15934      *
15935      * _.range(1, 4, 0);
15936      * // => [1, 1, 1]
15937      *
15938      * _.range(0);
15939      * // => []
15940      */
15941     var range = createRange();
15942
15943     /**
15944      * This method is like `_.range` except that it populates values in
15945      * descending order.
15946      *
15947      * @static
15948      * @memberOf _
15949      * @since 4.0.0
15950      * @category Util
15951      * @param {number} [start=0] The start of the range.
15952      * @param {number} end The end of the range.
15953      * @param {number} [step=1] The value to increment or decrement by.
15954      * @returns {Array} Returns the range of numbers.
15955      * @see _.inRange, _.range
15956      * @example
15957      *
15958      * _.rangeRight(4);
15959      * // => [3, 2, 1, 0]
15960      *
15961      * _.rangeRight(-4);
15962      * // => [-3, -2, -1, 0]
15963      *
15964      * _.rangeRight(1, 5);
15965      * // => [4, 3, 2, 1]
15966      *
15967      * _.rangeRight(0, 20, 5);
15968      * // => [15, 10, 5, 0]
15969      *
15970      * _.rangeRight(0, -4, -1);
15971      * // => [-3, -2, -1, 0]
15972      *
15973      * _.rangeRight(1, 4, 0);
15974      * // => [1, 1, 1]
15975      *
15976      * _.rangeRight(0);
15977      * // => []
15978      */
15979     var rangeRight = createRange(true);
15980
15981     /**
15982      * This method returns a new empty array.
15983      *
15984      * @static
15985      * @memberOf _
15986      * @since 4.13.0
15987      * @category Util
15988      * @returns {Array} Returns the new empty array.
15989      * @example
15990      *
15991      * var arrays = _.times(2, _.stubArray);
15992      *
15993      * console.log(arrays);
15994      * // => [[], []]
15995      *
15996      * console.log(arrays[0] === arrays[1]);
15997      * // => false
15998      */
15999     function stubArray() {
16000       return [];
16001     }
16002
16003     /**
16004      * This method returns `false`.
16005      *
16006      * @static
16007      * @memberOf _
16008      * @since 4.13.0
16009      * @category Util
16010      * @returns {boolean} Returns `false`.
16011      * @example
16012      *
16013      * _.times(2, _.stubFalse);
16014      * // => [false, false]
16015      */
16016     function stubFalse() {
16017       return false;
16018     }
16019
16020     /**
16021      * This method returns a new empty object.
16022      *
16023      * @static
16024      * @memberOf _
16025      * @since 4.13.0
16026      * @category Util
16027      * @returns {Object} Returns the new empty object.
16028      * @example
16029      *
16030      * var objects = _.times(2, _.stubObject);
16031      *
16032      * console.log(objects);
16033      * // => [{}, {}]
16034      *
16035      * console.log(objects[0] === objects[1]);
16036      * // => false
16037      */
16038     function stubObject() {
16039       return {};
16040     }
16041
16042     /**
16043      * This method returns an empty string.
16044      *
16045      * @static
16046      * @memberOf _
16047      * @since 4.13.0
16048      * @category Util
16049      * @returns {string} Returns the empty string.
16050      * @example
16051      *
16052      * _.times(2, _.stubString);
16053      * // => ['', '']
16054      */
16055     function stubString() {
16056       return '';
16057     }
16058
16059     /**
16060      * This method returns `true`.
16061      *
16062      * @static
16063      * @memberOf _
16064      * @since 4.13.0
16065      * @category Util
16066      * @returns {boolean} Returns `true`.
16067      * @example
16068      *
16069      * _.times(2, _.stubTrue);
16070      * // => [true, true]
16071      */
16072     function stubTrue() {
16073       return true;
16074     }
16075
16076     /**
16077      * Invokes the iteratee `n` times, returning an array of the results of
16078      * each invocation. The iteratee is invoked with one argument; (index).
16079      *
16080      * @static
16081      * @since 0.1.0
16082      * @memberOf _
16083      * @category Util
16084      * @param {number} n The number of times to invoke `iteratee`.
16085      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
16086      * @returns {Array} Returns the array of results.
16087      * @example
16088      *
16089      * _.times(3, String);
16090      * // => ['0', '1', '2']
16091      *
16092      *  _.times(4, _.constant(0));
16093      * // => [0, 0, 0, 0]
16094      */
16095     function times(n, iteratee) {
16096       n = toInteger(n);
16097       if (n < 1 || n > MAX_SAFE_INTEGER) {
16098         return [];
16099       }
16100       var index = MAX_ARRAY_LENGTH,
16101           length = nativeMin(n, MAX_ARRAY_LENGTH);
16102
16103       iteratee = getIteratee(iteratee);
16104       n -= MAX_ARRAY_LENGTH;
16105
16106       var result = baseTimes(length, iteratee);
16107       while (++index < n) {
16108         iteratee(index);
16109       }
16110       return result;
16111     }
16112
16113     /**
16114      * Converts `value` to a property path array.
16115      *
16116      * @static
16117      * @memberOf _
16118      * @since 4.0.0
16119      * @category Util
16120      * @param {*} value The value to convert.
16121      * @returns {Array} Returns the new property path array.
16122      * @example
16123      *
16124      * _.toPath('a.b.c');
16125      * // => ['a', 'b', 'c']
16126      *
16127      * _.toPath('a[0].b.c');
16128      * // => ['a', '0', 'b', 'c']
16129      */
16130     function toPath(value) {
16131       if (isArray(value)) {
16132         return arrayMap(value, toKey);
16133       }
16134       return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
16135     }
16136
16137     /**
16138      * Generates a unique ID. If `prefix` is given, the ID is appended to it.
16139      *
16140      * @static
16141      * @since 0.1.0
16142      * @memberOf _
16143      * @category Util
16144      * @param {string} [prefix=''] The value to prefix the ID with.
16145      * @returns {string} Returns the unique ID.
16146      * @example
16147      *
16148      * _.uniqueId('contact_');
16149      * // => 'contact_104'
16150      *
16151      * _.uniqueId();
16152      * // => '105'
16153      */
16154     function uniqueId(prefix) {
16155       var id = ++idCounter;
16156       return toString(prefix) + id;
16157     }
16158
16159     /*------------------------------------------------------------------------*/
16160
16161     /**
16162      * Adds two numbers.
16163      *
16164      * @static
16165      * @memberOf _
16166      * @since 3.4.0
16167      * @category Math
16168      * @param {number} augend The first number in an addition.
16169      * @param {number} addend The second number in an addition.
16170      * @returns {number} Returns the total.
16171      * @example
16172      *
16173      * _.add(6, 4);
16174      * // => 10
16175      */
16176     var add = createMathOperation(function(augend, addend) {
16177       return augend + addend;
16178     }, 0);
16179
16180     /**
16181      * Computes `number` rounded up to `precision`.
16182      *
16183      * @static
16184      * @memberOf _
16185      * @since 3.10.0
16186      * @category Math
16187      * @param {number} number The number to round up.
16188      * @param {number} [precision=0] The precision to round up to.
16189      * @returns {number} Returns the rounded up number.
16190      * @example
16191      *
16192      * _.ceil(4.006);
16193      * // => 5
16194      *
16195      * _.ceil(6.004, 2);
16196      * // => 6.01
16197      *
16198      * _.ceil(6040, -2);
16199      * // => 6100
16200      */
16201     var ceil = createRound('ceil');
16202
16203     /**
16204      * Divide two numbers.
16205      *
16206      * @static
16207      * @memberOf _
16208      * @since 4.7.0
16209      * @category Math
16210      * @param {number} dividend The first number in a division.
16211      * @param {number} divisor The second number in a division.
16212      * @returns {number} Returns the quotient.
16213      * @example
16214      *
16215      * _.divide(6, 4);
16216      * // => 1.5
16217      */
16218     var divide = createMathOperation(function(dividend, divisor) {
16219       return dividend / divisor;
16220     }, 1);
16221
16222     /**
16223      * Computes `number` rounded down to `precision`.
16224      *
16225      * @static
16226      * @memberOf _
16227      * @since 3.10.0
16228      * @category Math
16229      * @param {number} number The number to round down.
16230      * @param {number} [precision=0] The precision to round down to.
16231      * @returns {number} Returns the rounded down number.
16232      * @example
16233      *
16234      * _.floor(4.006);
16235      * // => 4
16236      *
16237      * _.floor(0.046, 2);
16238      * // => 0.04
16239      *
16240      * _.floor(4060, -2);
16241      * // => 4000
16242      */
16243     var floor = createRound('floor');
16244
16245     /**
16246      * Computes the maximum value of `array`. If `array` is empty or falsey,
16247      * `undefined` is returned.
16248      *
16249      * @static
16250      * @since 0.1.0
16251      * @memberOf _
16252      * @category Math
16253      * @param {Array} array The array to iterate over.
16254      * @returns {*} Returns the maximum value.
16255      * @example
16256      *
16257      * _.max([4, 2, 8, 6]);
16258      * // => 8
16259      *
16260      * _.max([]);
16261      * // => undefined
16262      */
16263     function max(array) {
16264       return (array && array.length)
16265         ? baseExtremum(array, identity, baseGt)
16266         : undefined;
16267     }
16268
16269     /**
16270      * This method is like `_.max` except that it accepts `iteratee` which is
16271      * invoked for each element in `array` to generate the criterion by which
16272      * the value is ranked. The iteratee is invoked with one argument: (value).
16273      *
16274      * @static
16275      * @memberOf _
16276      * @since 4.0.0
16277      * @category Math
16278      * @param {Array} array The array to iterate over.
16279      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16280      * @returns {*} Returns the maximum value.
16281      * @example
16282      *
16283      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16284      *
16285      * _.maxBy(objects, function(o) { return o.n; });
16286      * // => { 'n': 2 }
16287      *
16288      * // The `_.property` iteratee shorthand.
16289      * _.maxBy(objects, 'n');
16290      * // => { 'n': 2 }
16291      */
16292     function maxBy(array, iteratee) {
16293       return (array && array.length)
16294         ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
16295         : undefined;
16296     }
16297
16298     /**
16299      * Computes the mean of the values in `array`.
16300      *
16301      * @static
16302      * @memberOf _
16303      * @since 4.0.0
16304      * @category Math
16305      * @param {Array} array The array to iterate over.
16306      * @returns {number} Returns the mean.
16307      * @example
16308      *
16309      * _.mean([4, 2, 8, 6]);
16310      * // => 5
16311      */
16312     function mean(array) {
16313       return baseMean(array, identity);
16314     }
16315
16316     /**
16317      * This method is like `_.mean` except that it accepts `iteratee` which is
16318      * invoked for each element in `array` to generate the value to be averaged.
16319      * The iteratee is invoked with one argument: (value).
16320      *
16321      * @static
16322      * @memberOf _
16323      * @since 4.7.0
16324      * @category Math
16325      * @param {Array} array The array to iterate over.
16326      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16327      * @returns {number} Returns the mean.
16328      * @example
16329      *
16330      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16331      *
16332      * _.meanBy(objects, function(o) { return o.n; });
16333      * // => 5
16334      *
16335      * // The `_.property` iteratee shorthand.
16336      * _.meanBy(objects, 'n');
16337      * // => 5
16338      */
16339     function meanBy(array, iteratee) {
16340       return baseMean(array, getIteratee(iteratee, 2));
16341     }
16342
16343     /**
16344      * Computes the minimum value of `array`. If `array` is empty or falsey,
16345      * `undefined` is returned.
16346      *
16347      * @static
16348      * @since 0.1.0
16349      * @memberOf _
16350      * @category Math
16351      * @param {Array} array The array to iterate over.
16352      * @returns {*} Returns the minimum value.
16353      * @example
16354      *
16355      * _.min([4, 2, 8, 6]);
16356      * // => 2
16357      *
16358      * _.min([]);
16359      * // => undefined
16360      */
16361     function min(array) {
16362       return (array && array.length)
16363         ? baseExtremum(array, identity, baseLt)
16364         : undefined;
16365     }
16366
16367     /**
16368      * This method is like `_.min` except that it accepts `iteratee` which is
16369      * invoked for each element in `array` to generate the criterion by which
16370      * the value is ranked. The iteratee is invoked with one argument: (value).
16371      *
16372      * @static
16373      * @memberOf _
16374      * @since 4.0.0
16375      * @category Math
16376      * @param {Array} array The array to iterate over.
16377      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16378      * @returns {*} Returns the minimum value.
16379      * @example
16380      *
16381      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16382      *
16383      * _.minBy(objects, function(o) { return o.n; });
16384      * // => { 'n': 1 }
16385      *
16386      * // The `_.property` iteratee shorthand.
16387      * _.minBy(objects, 'n');
16388      * // => { 'n': 1 }
16389      */
16390     function minBy(array, iteratee) {
16391       return (array && array.length)
16392         ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
16393         : undefined;
16394     }
16395
16396     /**
16397      * Multiply two numbers.
16398      *
16399      * @static
16400      * @memberOf _
16401      * @since 4.7.0
16402      * @category Math
16403      * @param {number} multiplier The first number in a multiplication.
16404      * @param {number} multiplicand The second number in a multiplication.
16405      * @returns {number} Returns the product.
16406      * @example
16407      *
16408      * _.multiply(6, 4);
16409      * // => 24
16410      */
16411     var multiply = createMathOperation(function(multiplier, multiplicand) {
16412       return multiplier * multiplicand;
16413     }, 1);
16414
16415     /**
16416      * Computes `number` rounded to `precision`.
16417      *
16418      * @static
16419      * @memberOf _
16420      * @since 3.10.0
16421      * @category Math
16422      * @param {number} number The number to round.
16423      * @param {number} [precision=0] The precision to round to.
16424      * @returns {number} Returns the rounded number.
16425      * @example
16426      *
16427      * _.round(4.006);
16428      * // => 4
16429      *
16430      * _.round(4.006, 2);
16431      * // => 4.01
16432      *
16433      * _.round(4060, -2);
16434      * // => 4100
16435      */
16436     var round = createRound('round');
16437
16438     /**
16439      * Subtract two numbers.
16440      *
16441      * @static
16442      * @memberOf _
16443      * @since 4.0.0
16444      * @category Math
16445      * @param {number} minuend The first number in a subtraction.
16446      * @param {number} subtrahend The second number in a subtraction.
16447      * @returns {number} Returns the difference.
16448      * @example
16449      *
16450      * _.subtract(6, 4);
16451      * // => 2
16452      */
16453     var subtract = createMathOperation(function(minuend, subtrahend) {
16454       return minuend - subtrahend;
16455     }, 0);
16456
16457     /**
16458      * Computes the sum of the values in `array`.
16459      *
16460      * @static
16461      * @memberOf _
16462      * @since 3.4.0
16463      * @category Math
16464      * @param {Array} array The array to iterate over.
16465      * @returns {number} Returns the sum.
16466      * @example
16467      *
16468      * _.sum([4, 2, 8, 6]);
16469      * // => 20
16470      */
16471     function sum(array) {
16472       return (array && array.length)
16473         ? baseSum(array, identity)
16474         : 0;
16475     }
16476
16477     /**
16478      * This method is like `_.sum` except that it accepts `iteratee` which is
16479      * invoked for each element in `array` to generate the value to be summed.
16480      * The iteratee is invoked with one argument: (value).
16481      *
16482      * @static
16483      * @memberOf _
16484      * @since 4.0.0
16485      * @category Math
16486      * @param {Array} array The array to iterate over.
16487      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16488      * @returns {number} Returns the sum.
16489      * @example
16490      *
16491      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16492      *
16493      * _.sumBy(objects, function(o) { return o.n; });
16494      * // => 20
16495      *
16496      * // The `_.property` iteratee shorthand.
16497      * _.sumBy(objects, 'n');
16498      * // => 20
16499      */
16500     function sumBy(array, iteratee) {
16501       return (array && array.length)
16502         ? baseSum(array, getIteratee(iteratee, 2))
16503         : 0;
16504     }
16505
16506     /*------------------------------------------------------------------------*/
16507
16508     // Add methods that return wrapped values in chain sequences.
16509     lodash.after = after;
16510     lodash.ary = ary;
16511     lodash.assign = assign;
16512     lodash.assignIn = assignIn;
16513     lodash.assignInWith = assignInWith;
16514     lodash.assignWith = assignWith;
16515     lodash.at = at;
16516     lodash.before = before;
16517     lodash.bind = bind;
16518     lodash.bindAll = bindAll;
16519     lodash.bindKey = bindKey;
16520     lodash.castArray = castArray;
16521     lodash.chain = chain;
16522     lodash.chunk = chunk;
16523     lodash.compact = compact;
16524     lodash.concat = concat;
16525     lodash.cond = cond;
16526     lodash.conforms = conforms;
16527     lodash.constant = constant;
16528     lodash.countBy = countBy;
16529     lodash.create = create;
16530     lodash.curry = curry;
16531     lodash.curryRight = curryRight;
16532     lodash.debounce = debounce;
16533     lodash.defaults = defaults;
16534     lodash.defaultsDeep = defaultsDeep;
16535     lodash.defer = defer;
16536     lodash.delay = delay;
16537     lodash.difference = difference;
16538     lodash.differenceBy = differenceBy;
16539     lodash.differenceWith = differenceWith;
16540     lodash.drop = drop;
16541     lodash.dropRight = dropRight;
16542     lodash.dropRightWhile = dropRightWhile;
16543     lodash.dropWhile = dropWhile;
16544     lodash.fill = fill;
16545     lodash.filter = filter;
16546     lodash.flatMap = flatMap;
16547     lodash.flatMapDeep = flatMapDeep;
16548     lodash.flatMapDepth = flatMapDepth;
16549     lodash.flatten = flatten;
16550     lodash.flattenDeep = flattenDeep;
16551     lodash.flattenDepth = flattenDepth;
16552     lodash.flip = flip;
16553     lodash.flow = flow;
16554     lodash.flowRight = flowRight;
16555     lodash.fromPairs = fromPairs;
16556     lodash.functions = functions;
16557     lodash.functionsIn = functionsIn;
16558     lodash.groupBy = groupBy;
16559     lodash.initial = initial;
16560     lodash.intersection = intersection;
16561     lodash.intersectionBy = intersectionBy;
16562     lodash.intersectionWith = intersectionWith;
16563     lodash.invert = invert;
16564     lodash.invertBy = invertBy;
16565     lodash.invokeMap = invokeMap;
16566     lodash.iteratee = iteratee;
16567     lodash.keyBy = keyBy;
16568     lodash.keys = keys;
16569     lodash.keysIn = keysIn;
16570     lodash.map = map;
16571     lodash.mapKeys = mapKeys;
16572     lodash.mapValues = mapValues;
16573     lodash.matches = matches;
16574     lodash.matchesProperty = matchesProperty;
16575     lodash.memoize = memoize;
16576     lodash.merge = merge;
16577     lodash.mergeWith = mergeWith;
16578     lodash.method = method;
16579     lodash.methodOf = methodOf;
16580     lodash.mixin = mixin;
16581     lodash.negate = negate;
16582     lodash.nthArg = nthArg;
16583     lodash.omit = omit;
16584     lodash.omitBy = omitBy;
16585     lodash.once = once;
16586     lodash.orderBy = orderBy;
16587     lodash.over = over;
16588     lodash.overArgs = overArgs;
16589     lodash.overEvery = overEvery;
16590     lodash.overSome = overSome;
16591     lodash.partial = partial;
16592     lodash.partialRight = partialRight;
16593     lodash.partition = partition;
16594     lodash.pick = pick;
16595     lodash.pickBy = pickBy;
16596     lodash.property = property;
16597     lodash.propertyOf = propertyOf;
16598     lodash.pull = pull;
16599     lodash.pullAll = pullAll;
16600     lodash.pullAllBy = pullAllBy;
16601     lodash.pullAllWith = pullAllWith;
16602     lodash.pullAt = pullAt;
16603     lodash.range = range;
16604     lodash.rangeRight = rangeRight;
16605     lodash.rearg = rearg;
16606     lodash.reject = reject;
16607     lodash.remove = remove;
16608     lodash.rest = rest;
16609     lodash.reverse = reverse;
16610     lodash.sampleSize = sampleSize;
16611     lodash.set = set;
16612     lodash.setWith = setWith;
16613     lodash.shuffle = shuffle;
16614     lodash.slice = slice;
16615     lodash.sortBy = sortBy;
16616     lodash.sortedUniq = sortedUniq;
16617     lodash.sortedUniqBy = sortedUniqBy;
16618     lodash.split = split;
16619     lodash.spread = spread;
16620     lodash.tail = tail;
16621     lodash.take = take;
16622     lodash.takeRight = takeRight;
16623     lodash.takeRightWhile = takeRightWhile;
16624     lodash.takeWhile = takeWhile;
16625     lodash.tap = tap;
16626     lodash.throttle = throttle;
16627     lodash.thru = thru;
16628     lodash.toArray = toArray;
16629     lodash.toPairs = toPairs;
16630     lodash.toPairsIn = toPairsIn;
16631     lodash.toPath = toPath;
16632     lodash.toPlainObject = toPlainObject;
16633     lodash.transform = transform;
16634     lodash.unary = unary;
16635     lodash.union = union;
16636     lodash.unionBy = unionBy;
16637     lodash.unionWith = unionWith;
16638     lodash.uniq = uniq;
16639     lodash.uniqBy = uniqBy;
16640     lodash.uniqWith = uniqWith;
16641     lodash.unset = unset;
16642     lodash.unzip = unzip;
16643     lodash.unzipWith = unzipWith;
16644     lodash.update = update;
16645     lodash.updateWith = updateWith;
16646     lodash.values = values;
16647     lodash.valuesIn = valuesIn;
16648     lodash.without = without;
16649     lodash.words = words;
16650     lodash.wrap = wrap;
16651     lodash.xor = xor;
16652     lodash.xorBy = xorBy;
16653     lodash.xorWith = xorWith;
16654     lodash.zip = zip;
16655     lodash.zipObject = zipObject;
16656     lodash.zipObjectDeep = zipObjectDeep;
16657     lodash.zipWith = zipWith;
16658
16659     // Add aliases.
16660     lodash.entries = toPairs;
16661     lodash.entriesIn = toPairsIn;
16662     lodash.extend = assignIn;
16663     lodash.extendWith = assignInWith;
16664
16665     // Add methods to `lodash.prototype`.
16666     mixin(lodash, lodash);
16667
16668     /*------------------------------------------------------------------------*/
16669
16670     // Add methods that return unwrapped values in chain sequences.
16671     lodash.add = add;
16672     lodash.attempt = attempt;
16673     lodash.camelCase = camelCase;
16674     lodash.capitalize = capitalize;
16675     lodash.ceil = ceil;
16676     lodash.clamp = clamp;
16677     lodash.clone = clone;
16678     lodash.cloneDeep = cloneDeep;
16679     lodash.cloneDeepWith = cloneDeepWith;
16680     lodash.cloneWith = cloneWith;
16681     lodash.conformsTo = conformsTo;
16682     lodash.deburr = deburr;
16683     lodash.defaultTo = defaultTo;
16684     lodash.divide = divide;
16685     lodash.endsWith = endsWith;
16686     lodash.eq = eq;
16687     lodash.escape = escape;
16688     lodash.escapeRegExp = escapeRegExp;
16689     lodash.every = every;
16690     lodash.find = find;
16691     lodash.findIndex = findIndex;
16692     lodash.findKey = findKey;
16693     lodash.findLast = findLast;
16694     lodash.findLastIndex = findLastIndex;
16695     lodash.findLastKey = findLastKey;
16696     lodash.floor = floor;
16697     lodash.forEach = forEach;
16698     lodash.forEachRight = forEachRight;
16699     lodash.forIn = forIn;
16700     lodash.forInRight = forInRight;
16701     lodash.forOwn = forOwn;
16702     lodash.forOwnRight = forOwnRight;
16703     lodash.get = get;
16704     lodash.gt = gt;
16705     lodash.gte = gte;
16706     lodash.has = has;
16707     lodash.hasIn = hasIn;
16708     lodash.head = head;
16709     lodash.identity = identity;
16710     lodash.includes = includes;
16711     lodash.indexOf = indexOf;
16712     lodash.inRange = inRange;
16713     lodash.invoke = invoke;
16714     lodash.isArguments = isArguments;
16715     lodash.isArray = isArray;
16716     lodash.isArrayBuffer = isArrayBuffer;
16717     lodash.isArrayLike = isArrayLike;
16718     lodash.isArrayLikeObject = isArrayLikeObject;
16719     lodash.isBoolean = isBoolean;
16720     lodash.isBuffer = isBuffer;
16721     lodash.isDate = isDate;
16722     lodash.isElement = isElement;
16723     lodash.isEmpty = isEmpty;
16724     lodash.isEqual = isEqual;
16725     lodash.isEqualWith = isEqualWith;
16726     lodash.isError = isError;
16727     lodash.isFinite = isFinite;
16728     lodash.isFunction = isFunction;
16729     lodash.isInteger = isInteger;
16730     lodash.isLength = isLength;
16731     lodash.isMap = isMap;
16732     lodash.isMatch = isMatch;
16733     lodash.isMatchWith = isMatchWith;
16734     lodash.isNaN = isNaN;
16735     lodash.isNative = isNative;
16736     lodash.isNil = isNil;
16737     lodash.isNull = isNull;
16738     lodash.isNumber = isNumber;
16739     lodash.isObject = isObject;
16740     lodash.isObjectLike = isObjectLike;
16741     lodash.isPlainObject = isPlainObject;
16742     lodash.isRegExp = isRegExp;
16743     lodash.isSafeInteger = isSafeInteger;
16744     lodash.isSet = isSet;
16745     lodash.isString = isString;
16746     lodash.isSymbol = isSymbol;
16747     lodash.isTypedArray = isTypedArray;
16748     lodash.isUndefined = isUndefined;
16749     lodash.isWeakMap = isWeakMap;
16750     lodash.isWeakSet = isWeakSet;
16751     lodash.join = join;
16752     lodash.kebabCase = kebabCase;
16753     lodash.last = last;
16754     lodash.lastIndexOf = lastIndexOf;
16755     lodash.lowerCase = lowerCase;
16756     lodash.lowerFirst = lowerFirst;
16757     lodash.lt = lt;
16758     lodash.lte = lte;
16759     lodash.max = max;
16760     lodash.maxBy = maxBy;
16761     lodash.mean = mean;
16762     lodash.meanBy = meanBy;
16763     lodash.min = min;
16764     lodash.minBy = minBy;
16765     lodash.stubArray = stubArray;
16766     lodash.stubFalse = stubFalse;
16767     lodash.stubObject = stubObject;
16768     lodash.stubString = stubString;
16769     lodash.stubTrue = stubTrue;
16770     lodash.multiply = multiply;
16771     lodash.nth = nth;
16772     lodash.noConflict = noConflict;
16773     lodash.noop = noop;
16774     lodash.now = now;
16775     lodash.pad = pad;
16776     lodash.padEnd = padEnd;
16777     lodash.padStart = padStart;
16778     lodash.parseInt = parseInt;
16779     lodash.random = random;
16780     lodash.reduce = reduce;
16781     lodash.reduceRight = reduceRight;
16782     lodash.repeat = repeat;
16783     lodash.replace = replace;
16784     lodash.result = result;
16785     lodash.round = round;
16786     lodash.runInContext = runInContext;
16787     lodash.sample = sample;
16788     lodash.size = size;
16789     lodash.snakeCase = snakeCase;
16790     lodash.some = some;
16791     lodash.sortedIndex = sortedIndex;
16792     lodash.sortedIndexBy = sortedIndexBy;
16793     lodash.sortedIndexOf = sortedIndexOf;
16794     lodash.sortedLastIndex = sortedLastIndex;
16795     lodash.sortedLastIndexBy = sortedLastIndexBy;
16796     lodash.sortedLastIndexOf = sortedLastIndexOf;
16797     lodash.startCase = startCase;
16798     lodash.startsWith = startsWith;
16799     lodash.subtract = subtract;
16800     lodash.sum = sum;
16801     lodash.sumBy = sumBy;
16802     lodash.template = template;
16803     lodash.times = times;
16804     lodash.toFinite = toFinite;
16805     lodash.toInteger = toInteger;
16806     lodash.toLength = toLength;
16807     lodash.toLower = toLower;
16808     lodash.toNumber = toNumber;
16809     lodash.toSafeInteger = toSafeInteger;
16810     lodash.toString = toString;
16811     lodash.toUpper = toUpper;
16812     lodash.trim = trim;
16813     lodash.trimEnd = trimEnd;
16814     lodash.trimStart = trimStart;
16815     lodash.truncate = truncate;
16816     lodash.unescape = unescape;
16817     lodash.uniqueId = uniqueId;
16818     lodash.upperCase = upperCase;
16819     lodash.upperFirst = upperFirst;
16820
16821     // Add aliases.
16822     lodash.each = forEach;
16823     lodash.eachRight = forEachRight;
16824     lodash.first = head;
16825
16826     mixin(lodash, (function() {
16827       var source = {};
16828       baseForOwn(lodash, function(func, methodName) {
16829         if (!hasOwnProperty.call(lodash.prototype, methodName)) {
16830           source[methodName] = func;
16831         }
16832       });
16833       return source;
16834     }()), { 'chain': false });
16835
16836     /*------------------------------------------------------------------------*/
16837
16838     /**
16839      * The semantic version number.
16840      *
16841      * @static
16842      * @memberOf _
16843      * @type {string}
16844      */
16845     lodash.VERSION = VERSION;
16846
16847     // Assign default placeholders.
16848     arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
16849       lodash[methodName].placeholder = lodash;
16850     });
16851
16852     // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
16853     arrayEach(['drop', 'take'], function(methodName, index) {
16854       LazyWrapper.prototype[methodName] = function(n) {
16855         var filtered = this.__filtered__;
16856         if (filtered && !index) {
16857           return new LazyWrapper(this);
16858         }
16859         n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
16860
16861         var result = this.clone();
16862         if (filtered) {
16863           result.__takeCount__ = nativeMin(n, result.__takeCount__);
16864         } else {
16865           result.__views__.push({
16866             'size': nativeMin(n, MAX_ARRAY_LENGTH),
16867             'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
16868           });
16869         }
16870         return result;
16871       };
16872
16873       LazyWrapper.prototype[methodName + 'Right'] = function(n) {
16874         return this.reverse()[methodName](n).reverse();
16875       };
16876     });
16877
16878     // Add `LazyWrapper` methods that accept an `iteratee` value.
16879     arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
16880       var type = index + 1,
16881           isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
16882
16883       LazyWrapper.prototype[methodName] = function(iteratee) {
16884         var result = this.clone();
16885         result.__iteratees__.push({
16886           'iteratee': getIteratee(iteratee, 3),
16887           'type': type
16888         });
16889         result.__filtered__ = result.__filtered__ || isFilter;
16890         return result;
16891       };
16892     });
16893
16894     // Add `LazyWrapper` methods for `_.head` and `_.last`.
16895     arrayEach(['head', 'last'], function(methodName, index) {
16896       var takeName = 'take' + (index ? 'Right' : '');
16897
16898       LazyWrapper.prototype[methodName] = function() {
16899         return this[takeName](1).value()[0];
16900       };
16901     });
16902
16903     // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
16904     arrayEach(['initial', 'tail'], function(methodName, index) {
16905       var dropName = 'drop' + (index ? '' : 'Right');
16906
16907       LazyWrapper.prototype[methodName] = function() {
16908         return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
16909       };
16910     });
16911
16912     LazyWrapper.prototype.compact = function() {
16913       return this.filter(identity);
16914     };
16915
16916     LazyWrapper.prototype.find = function(predicate) {
16917       return this.filter(predicate).head();
16918     };
16919
16920     LazyWrapper.prototype.findLast = function(predicate) {
16921       return this.reverse().find(predicate);
16922     };
16923
16924     LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
16925       if (typeof path == 'function') {
16926         return new LazyWrapper(this);
16927       }
16928       return this.map(function(value) {
16929         return baseInvoke(value, path, args);
16930       });
16931     });
16932
16933     LazyWrapper.prototype.reject = function(predicate) {
16934       return this.filter(negate(getIteratee(predicate)));
16935     };
16936
16937     LazyWrapper.prototype.slice = function(start, end) {
16938       start = toInteger(start);
16939
16940       var result = this;
16941       if (result.__filtered__ && (start > 0 || end < 0)) {
16942         return new LazyWrapper(result);
16943       }
16944       if (start < 0) {
16945         result = result.takeRight(-start);
16946       } else if (start) {
16947         result = result.drop(start);
16948       }
16949       if (end !== undefined) {
16950         end = toInteger(end);
16951         result = end < 0 ? result.dropRight(-end) : result.take(end - start);
16952       }
16953       return result;
16954     };
16955
16956     LazyWrapper.prototype.takeRightWhile = function(predicate) {
16957       return this.reverse().takeWhile(predicate).reverse();
16958     };
16959
16960     LazyWrapper.prototype.toArray = function() {
16961       return this.take(MAX_ARRAY_LENGTH);
16962     };
16963
16964     // Add `LazyWrapper` methods to `lodash.prototype`.
16965     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
16966       var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
16967           isTaker = /^(?:head|last)$/.test(methodName),
16968           lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
16969           retUnwrapped = isTaker || /^find/.test(methodName);
16970
16971       if (!lodashFunc) {
16972         return;
16973       }
16974       lodash.prototype[methodName] = function() {
16975         var value = this.__wrapped__,
16976             args = isTaker ? [1] : arguments,
16977             isLazy = value instanceof LazyWrapper,
16978             iteratee = args[0],
16979             useLazy = isLazy || isArray(value);
16980
16981         var interceptor = function(value) {
16982           var result = lodashFunc.apply(lodash, arrayPush([value], args));
16983           return (isTaker && chainAll) ? result[0] : result;
16984         };
16985
16986         if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
16987           // Avoid lazy use if the iteratee has a "length" value other than `1`.
16988           isLazy = useLazy = false;
16989         }
16990         var chainAll = this.__chain__,
16991             isHybrid = !!this.__actions__.length,
16992             isUnwrapped = retUnwrapped && !chainAll,
16993             onlyLazy = isLazy && !isHybrid;
16994
16995         if (!retUnwrapped && useLazy) {
16996           value = onlyLazy ? value : new LazyWrapper(this);
16997           var result = func.apply(value, args);
16998           result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
16999           return new LodashWrapper(result, chainAll);
17000         }
17001         if (isUnwrapped && onlyLazy) {
17002           return func.apply(this, args);
17003         }
17004         result = this.thru(interceptor);
17005         return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
17006       };
17007     });
17008
17009     // Add `Array` methods to `lodash.prototype`.
17010     arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
17011       var func = arrayProto[methodName],
17012           chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
17013           retUnwrapped = /^(?:pop|shift)$/.test(methodName);
17014
17015       lodash.prototype[methodName] = function() {
17016         var args = arguments;
17017         if (retUnwrapped && !this.__chain__) {
17018           var value = this.value();
17019           return func.apply(isArray(value) ? value : [], args);
17020         }
17021         return this[chainName](function(value) {
17022           return func.apply(isArray(value) ? value : [], args);
17023         });
17024       };
17025     });
17026
17027     // Map minified method names to their real names.
17028     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
17029       var lodashFunc = lodash[methodName];
17030       if (lodashFunc) {
17031         var key = (lodashFunc.name + ''),
17032             names = realNames[key] || (realNames[key] = []);
17033
17034         names.push({ 'name': methodName, 'func': lodashFunc });
17035       }
17036     });
17037
17038     realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
17039       'name': 'wrapper',
17040       'func': undefined
17041     }];
17042
17043     // Add methods to `LazyWrapper`.
17044     LazyWrapper.prototype.clone = lazyClone;
17045     LazyWrapper.prototype.reverse = lazyReverse;
17046     LazyWrapper.prototype.value = lazyValue;
17047
17048     // Add chain sequence methods to the `lodash` wrapper.
17049     lodash.prototype.at = wrapperAt;
17050     lodash.prototype.chain = wrapperChain;
17051     lodash.prototype.commit = wrapperCommit;
17052     lodash.prototype.next = wrapperNext;
17053     lodash.prototype.plant = wrapperPlant;
17054     lodash.prototype.reverse = wrapperReverse;
17055     lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
17056
17057     // Add lazy aliases.
17058     lodash.prototype.first = lodash.prototype.head;
17059
17060     if (symIterator) {
17061       lodash.prototype[symIterator] = wrapperToIterator;
17062     }
17063     return lodash;
17064   });
17065
17066   /*--------------------------------------------------------------------------*/
17067
17068   // Export lodash.
17069   var _ = runInContext();
17070
17071   // Some AMD build optimizers, like r.js, check for condition patterns like:
17072   if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
17073     // Expose Lodash on the global object to prevent errors when Lodash is
17074     // loaded by a script tag in the presence of an AMD loader.
17075     // See http://requirejs.org/docs/errors.html#mismatch for more details.
17076     // Use `_.noConflict` to remove Lodash from the global object.
17077     root._ = _;
17078
17079     // Define as an anonymous module so, through path mapping, it can be
17080     // referenced as the "underscore" module.
17081     define(function() {
17082       return _;
17083     });
17084   }
17085   // Check for `exports` after `define` in case a build optimizer adds it.
17086   else if (freeModule) {
17087     // Export for Node.js.
17088     (freeModule.exports = _)._ = _;
17089     // Export for CommonJS support.
17090     freeExports._ = _;
17091   }
17092   else {
17093     // Export to the global object.
17094     root._ = _;
17095   }
17096 }.call(commonjsGlobal));
17097 });
17098
17099 function osmIsInterestingTag(key) {
17100     return key !== 'attribution' &&
17101         key !== 'created_by' &&
17102         key !== 'source' &&
17103         key !== 'odbl' &&
17104         key.indexOf('tiger:') !== 0;
17105
17106 }
17107
17108
17109 var osmOneWayTags = {
17110     'aerialway': {
17111         'chair_lift': true,
17112         'mixed_lift': true,
17113         't-bar': true,
17114         'j-bar': true,
17115         'platter': true,
17116         'rope_tow': true,
17117         'magic_carpet': true,
17118         'yes': true
17119     },
17120     'highway': {
17121         'motorway': true,
17122         'motorway_link': true
17123     },
17124     'junction': {
17125         'roundabout': true
17126     },
17127     'man_made': {
17128         'piste:halfpipe': true
17129     },
17130     'piste:type': {
17131         'downhill': true,
17132         'sled': true,
17133         'yes': true
17134     },
17135     'waterway': {
17136         'river': true,
17137         'stream': true
17138     }
17139 };
17140
17141
17142 var osmPavedTags = {
17143     'surface': {
17144         'paved': true,
17145         'asphalt': true,
17146         'concrete': true
17147     },
17148     'tracktype': {
17149         'grade1': true
17150     }
17151 };
17152
17153 var dataWikipedia = [
17154     [
17155         "Abkhazian",
17156         "Аҧсшәа",
17157         "ab"
17158     ],
17159     [
17160         "Achinese",
17161         "Acèh",
17162         "ace"
17163     ],
17164     [
17165         "Adyghe",
17166         "адыгабзэ",
17167         "ady"
17168     ],
17169     [
17170         "Afrikaans",
17171         "Afrikaans",
17172         "af"
17173     ],
17174     [
17175         "Akan",
17176         "Akan",
17177         "ak"
17178     ],
17179     [
17180         "Alemannisch",
17181         "Alemannisch",
17182         "als"
17183     ],
17184     [
17185         "Amharic",
17186         "አማርኛ",
17187         "am"
17188     ],
17189     [
17190         "Aragonese",
17191         "aragonés",
17192         "an"
17193     ],
17194     [
17195         "Old English",
17196         "Ænglisc",
17197         "ang"
17198     ],
17199     [
17200         "Arabic",
17201         "العربية",
17202         "ar"
17203     ],
17204     [
17205         "Aramaic",
17206         "ܐܪܡܝܐ",
17207         "arc"
17208     ],
17209     [
17210         "Egyptian Arabic",
17211         "مصرى",
17212         "arz"
17213     ],
17214     [
17215         "Assamese",
17216         "অসমীয়া",
17217         "as"
17218     ],
17219     [
17220         "Asturian",
17221         "asturianu",
17222         "ast"
17223     ],
17224     [
17225         "Avaric",
17226         "авар",
17227         "av"
17228     ],
17229     [
17230         "Aymara",
17231         "Aymar aru",
17232         "ay"
17233     ],
17234     [
17235         "Azerbaijani",
17236         "azərbaycanca",
17237         "az"
17238     ],
17239     [
17240         "تۆرکجه",
17241         "تۆرکجه",
17242         "azb"
17243     ],
17244     [
17245         "Bashkir",
17246         "башҡортса",
17247         "ba"
17248     ],
17249     [
17250         "Bavarian",
17251         "Boarisch",
17252         "bar"
17253     ],
17254     [
17255         "Samogitian",
17256         "žemaitėška",
17257         "bat-smg"
17258     ],
17259     [
17260         "Bikol Central",
17261         "Bikol Central",
17262         "bcl"
17263     ],
17264     [
17265         "Belarusian",
17266         "беларуская",
17267         "be"
17268     ],
17269     [
17270         "беларуская (тарашкевіца)‎",
17271         "беларуская (тарашкевіца)‎",
17272         "be-x-old"
17273     ],
17274     [
17275         "Bulgarian",
17276         "български",
17277         "bg"
17278     ],
17279     [
17280         "भोजपुरी",
17281         "भोजपुरी",
17282         "bh"
17283     ],
17284     [
17285         "Bislama",
17286         "Bislama",
17287         "bi"
17288     ],
17289     [
17290         "Banjar",
17291         "Bahasa Banjar",
17292         "bjn"
17293     ],
17294     [
17295         "Bambara",
17296         "bamanankan",
17297         "bm"
17298     ],
17299     [
17300         "Bengali",
17301         "বাংলা",
17302         "bn"
17303     ],
17304     [
17305         "Tibetan",
17306         "བོད་ཡིག",
17307         "bo"
17308     ],
17309     [
17310         "Bishnupriya",
17311         "বিষ্ণুপ্রিয়া মণিপুরী",
17312         "bpy"
17313     ],
17314     [
17315         "Breton",
17316         "brezhoneg",
17317         "br"
17318     ],
17319     [
17320         "Bosnian",
17321         "bosanski",
17322         "bs"
17323     ],
17324     [
17325         "Buginese",
17326         "ᨅᨔ ᨕᨘᨁᨗ",
17327         "bug"
17328     ],
17329     [
17330         "буряад",
17331         "буряад",
17332         "bxr"
17333     ],
17334     [
17335         "Catalan",
17336         "català",
17337         "ca"
17338     ],
17339     [
17340         "Chavacano de Zamboanga",
17341         "Chavacano de Zamboanga",
17342         "cbk-zam"
17343     ],
17344     [
17345         "Min Dong Chinese",
17346         "Mìng-dĕ̤ng-ngṳ̄",
17347         "cdo"
17348     ],
17349     [
17350         "Chechen",
17351         "нохчийн",
17352         "ce"
17353     ],
17354     [
17355         "Cebuano",
17356         "Cebuano",
17357         "ceb"
17358     ],
17359     [
17360         "Chamorro",
17361         "Chamoru",
17362         "ch"
17363     ],
17364     [
17365         "Cherokee",
17366         "ᏣᎳᎩ",
17367         "chr"
17368     ],
17369     [
17370         "Cheyenne",
17371         "Tsetsêhestâhese",
17372         "chy"
17373     ],
17374     [
17375         "Central Kurdish",
17376         "کوردیی ناوەندی",
17377         "ckb"
17378     ],
17379     [
17380         "Corsican",
17381         "corsu",
17382         "co"
17383     ],
17384     [
17385         "Cree",
17386         "Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ",
17387         "cr"
17388     ],
17389     [
17390         "Crimean Turkish",
17391         "qırımtatarca",
17392         "crh"
17393     ],
17394     [
17395         "Czech",
17396         "čeština",
17397         "cs"
17398     ],
17399     [
17400         "Kashubian",
17401         "kaszëbsczi",
17402         "csb"
17403     ],
17404     [
17405         "Church Slavic",
17406         "словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ",
17407         "cu"
17408     ],
17409     [
17410         "Chuvash",
17411         "Чӑвашла",
17412         "cv"
17413     ],
17414     [
17415         "Welsh",
17416         "Cymraeg",
17417         "cy"
17418     ],
17419     [
17420         "Danish",
17421         "dansk",
17422         "da"
17423     ],
17424     [
17425         "German",
17426         "Deutsch",
17427         "de"
17428     ],
17429     [
17430         "Zazaki",
17431         "Zazaki",
17432         "diq"
17433     ],
17434     [
17435         "Lower Sorbian",
17436         "dolnoserbski",
17437         "dsb"
17438     ],
17439     [
17440         "Divehi",
17441         "ދިވެހިބަސް",
17442         "dv"
17443     ],
17444     [
17445         "Dzongkha",
17446         "ཇོང་ཁ",
17447         "dz"
17448     ],
17449     [
17450         "Ewe",
17451         "eʋegbe",
17452         "ee"
17453     ],
17454     [
17455         "Greek",
17456         "Ελληνικά",
17457         "el"
17458     ],
17459     [
17460         "Emiliano-Romagnolo",
17461         "emiliàn e rumagnòl",
17462         "eml"
17463     ],
17464     [
17465         "English",
17466         "English",
17467         "en"
17468     ],
17469     [
17470         "Esperanto",
17471         "Esperanto",
17472         "eo"
17473     ],
17474     [
17475         "Spanish",
17476         "español",
17477         "es"
17478     ],
17479     [
17480         "Estonian",
17481         "eesti",
17482         "et"
17483     ],
17484     [
17485         "Basque",
17486         "euskara",
17487         "eu"
17488     ],
17489     [
17490         "Extremaduran",
17491         "estremeñu",
17492         "ext"
17493     ],
17494     [
17495         "Persian",
17496         "فارسی",
17497         "fa"
17498     ],
17499     [
17500         "Fulah",
17501         "Fulfulde",
17502         "ff"
17503     ],
17504     [
17505         "Finnish",
17506         "suomi",
17507         "fi"
17508     ],
17509     [
17510         "Võro",
17511         "Võro",
17512         "fiu-vro"
17513     ],
17514     [
17515         "Fijian",
17516         "Na Vosa Vakaviti",
17517         "fj"
17518     ],
17519     [
17520         "Faroese",
17521         "føroyskt",
17522         "fo"
17523     ],
17524     [
17525         "French",
17526         "français",
17527         "fr"
17528     ],
17529     [
17530         "Arpitan",
17531         "arpetan",
17532         "frp"
17533     ],
17534     [
17535         "Northern Frisian",
17536         "Nordfriisk",
17537         "frr"
17538     ],
17539     [
17540         "Friulian",
17541         "furlan",
17542         "fur"
17543     ],
17544     [
17545         "Western Frisian",
17546         "Frysk",
17547         "fy"
17548     ],
17549     [
17550         "Irish",
17551         "Gaeilge",
17552         "ga"
17553     ],
17554     [
17555         "Gagauz",
17556         "Gagauz",
17557         "gag"
17558     ],
17559     [
17560         "Gan Chinese",
17561         "贛語",
17562         "gan"
17563     ],
17564     [
17565         "Scottish Gaelic",
17566         "Gàidhlig",
17567         "gd"
17568     ],
17569     [
17570         "Galician",
17571         "galego",
17572         "gl"
17573     ],
17574     [
17575         "Gilaki",
17576         "گیلکی",
17577         "glk"
17578     ],
17579     [
17580         "Guarani",
17581         "Avañe'ẽ",
17582         "gn"
17583     ],
17584     [
17585         "Goan Konkani",
17586         "गोंयची कोंकणी / Gõychi Konknni",
17587         "gom"
17588     ],
17589     [
17590         "Gothic",
17591         "𐌲𐌿𐍄𐌹𐍃𐌺",
17592         "got"
17593     ],
17594     [
17595         "Gujarati",
17596         "ગુજરાતી",
17597         "gu"
17598     ],
17599     [
17600         "Manx",
17601         "Gaelg",
17602         "gv"
17603     ],
17604     [
17605         "Hausa",
17606         "Hausa",
17607         "ha"
17608     ],
17609     [
17610         "Hakka Chinese",
17611         "客家語/Hak-kâ-ngî",
17612         "hak"
17613     ],
17614     [
17615         "Hawaiian",
17616         "Hawaiʻi",
17617         "haw"
17618     ],
17619     [
17620         "Hebrew",
17621         "עברית",
17622         "he"
17623     ],
17624     [
17625         "Hindi",
17626         "हिन्दी",
17627         "hi"
17628     ],
17629     [
17630         "Fiji Hindi",
17631         "Fiji Hindi",
17632         "hif"
17633     ],
17634     [
17635         "Croatian",
17636         "hrvatski",
17637         "hr"
17638     ],
17639     [
17640         "Upper Sorbian",
17641         "hornjoserbsce",
17642         "hsb"
17643     ],
17644     [
17645         "Haitian Creole",
17646         "Kreyòl ayisyen",
17647         "ht"
17648     ],
17649     [
17650         "Hungarian",
17651         "magyar",
17652         "hu"
17653     ],
17654     [
17655         "Armenian",
17656         "Հայերեն",
17657         "hy"
17658     ],
17659     [
17660         "Interlingua",
17661         "interlingua",
17662         "ia"
17663     ],
17664     [
17665         "Indonesian",
17666         "Bahasa Indonesia",
17667         "id"
17668     ],
17669     [
17670         "Interlingue",
17671         "Interlingue",
17672         "ie"
17673     ],
17674     [
17675         "Igbo",
17676         "Igbo",
17677         "ig"
17678     ],
17679     [
17680         "Inupiaq",
17681         "Iñupiak",
17682         "ik"
17683     ],
17684     [
17685         "Iloko",
17686         "Ilokano",
17687         "ilo"
17688     ],
17689     [
17690         "Ido",
17691         "Ido",
17692         "io"
17693     ],
17694     [
17695         "Icelandic",
17696         "íslenska",
17697         "is"
17698     ],
17699     [
17700         "Italian",
17701         "italiano",
17702         "it"
17703     ],
17704     [
17705         "Inuktitut",
17706         "ᐃᓄᒃᑎᑐᑦ/inuktitut",
17707         "iu"
17708     ],
17709     [
17710         "Japanese",
17711         "日本語",
17712         "ja"
17713     ],
17714     [
17715         "Jamaican Creole English",
17716         "Patois",
17717         "jam"
17718     ],
17719     [
17720         "Lojban",
17721         "la .lojban.",
17722         "jbo"
17723     ],
17724     [
17725         "Javanese",
17726         "Basa Jawa",
17727         "jv"
17728     ],
17729     [
17730         "Georgian",
17731         "ქართული",
17732         "ka"
17733     ],
17734     [
17735         "Kara-Kalpak",
17736         "Qaraqalpaqsha",
17737         "kaa"
17738     ],
17739     [
17740         "Kabyle",
17741         "Taqbaylit",
17742         "kab"
17743     ],
17744     [
17745         "Kabardian",
17746         "Адыгэбзэ",
17747         "kbd"
17748     ],
17749     [
17750         "Kongo",
17751         "Kongo",
17752         "kg"
17753     ],
17754     [
17755         "Kikuyu",
17756         "Gĩkũyũ",
17757         "ki"
17758     ],
17759     [
17760         "Kazakh",
17761         "қазақша",
17762         "kk"
17763     ],
17764     [
17765         "Kalaallisut",
17766         "kalaallisut",
17767         "kl"
17768     ],
17769     [
17770         "Khmer",
17771         "ភាសាខ្មែរ",
17772         "km"
17773     ],
17774     [
17775         "Kannada",
17776         "ಕನ್ನಡ",
17777         "kn"
17778     ],
17779     [
17780         "Korean",
17781         "한국어",
17782         "ko"
17783     ],
17784     [
17785         "Komi-Permyak",
17786         "Перем Коми",
17787         "koi"
17788     ],
17789     [
17790         "Karachay-Balkar",
17791         "къарачай-малкъар",
17792         "krc"
17793     ],
17794     [
17795         "Kashmiri",
17796         "कॉशुर / کٲشُر",
17797         "ks"
17798     ],
17799     [
17800         "Colognian",
17801         "Ripoarisch",
17802         "ksh"
17803     ],
17804     [
17805         "Kurdish",
17806         "Kurdî",
17807         "ku"
17808     ],
17809     [
17810         "Komi",
17811         "коми",
17812         "kv"
17813     ],
17814     [
17815         "Cornish",
17816         "kernowek",
17817         "kw"
17818     ],
17819     [
17820         "Kyrgyz",
17821         "Кыргызча",
17822         "ky"
17823     ],
17824     [
17825         "Latin",
17826         "Latina",
17827         "la"
17828     ],
17829     [
17830         "Ladino",
17831         "Ladino",
17832         "lad"
17833     ],
17834     [
17835         "Luxembourgish",
17836         "Lëtzebuergesch",
17837         "lb"
17838     ],
17839     [
17840         "лакку",
17841         "лакку",
17842         "lbe"
17843     ],
17844     [
17845         "Lezghian",
17846         "лезги",
17847         "lez"
17848     ],
17849     [
17850         "Ganda",
17851         "Luganda",
17852         "lg"
17853     ],
17854     [
17855         "Limburgish",
17856         "Limburgs",
17857         "li"
17858     ],
17859     [
17860         "Ligurian",
17861         "Ligure",
17862         "lij"
17863     ],
17864     [
17865         "Lombard",
17866         "lumbaart",
17867         "lmo"
17868     ],
17869     [
17870         "Lingala",
17871         "lingála",
17872         "ln"
17873     ],
17874     [
17875         "Lao",
17876         "ລາວ",
17877         "lo"
17878     ],
17879     [
17880         "Northern Luri",
17881         "لۊری شومالی",
17882         "lrc"
17883     ],
17884     [
17885         "Lithuanian",
17886         "lietuvių",
17887         "lt"
17888     ],
17889     [
17890         "Latgalian",
17891         "latgaļu",
17892         "ltg"
17893     ],
17894     [
17895         "Latvian",
17896         "latviešu",
17897         "lv"
17898     ],
17899     [
17900         "Maithili",
17901         "मैथिली",
17902         "mai"
17903     ],
17904     [
17905         "Basa Banyumasan",
17906         "Basa Banyumasan",
17907         "map-bms"
17908     ],
17909     [
17910         "Moksha",
17911         "мокшень",
17912         "mdf"
17913     ],
17914     [
17915         "Malagasy",
17916         "Malagasy",
17917         "mg"
17918     ],
17919     [
17920         "Eastern Mari",
17921         "олык марий",
17922         "mhr"
17923     ],
17924     [
17925         "Maori",
17926         "Māori",
17927         "mi"
17928     ],
17929     [
17930         "Minangkabau",
17931         "Baso Minangkabau",
17932         "min"
17933     ],
17934     [
17935         "Macedonian",
17936         "македонски",
17937         "mk"
17938     ],
17939     [
17940         "Malayalam",
17941         "മലയാളം",
17942         "ml"
17943     ],
17944     [
17945         "Mongolian",
17946         "монгол",
17947         "mn"
17948     ],
17949     [
17950         "Marathi",
17951         "मराठी",
17952         "mr"
17953     ],
17954     [
17955         "Western Mari",
17956         "кырык мары",
17957         "mrj"
17958     ],
17959     [
17960         "Malay",
17961         "Bahasa Melayu",
17962         "ms"
17963     ],
17964     [
17965         "Maltese",
17966         "Malti",
17967         "mt"
17968     ],
17969     [
17970         "Mirandese",
17971         "Mirandés",
17972         "mwl"
17973     ],
17974     [
17975         "Burmese",
17976         "မြန်မာဘာသာ",
17977         "my"
17978     ],
17979     [
17980         "Erzya",
17981         "эрзянь",
17982         "myv"
17983     ],
17984     [
17985         "Mazanderani",
17986         "مازِرونی",
17987         "mzn"
17988     ],
17989     [
17990         "Nauru",
17991         "Dorerin Naoero",
17992         "na"
17993     ],
17994     [
17995         "Nāhuatl",
17996         "Nāhuatl",
17997         "nah"
17998     ],
17999     [
18000         "Neapolitan",
18001         "Napulitano",
18002         "nap"
18003     ],
18004     [
18005         "Low German",
18006         "Plattdüütsch",
18007         "nds"
18008     ],
18009     [
18010         "Low Saxon",
18011         "Nedersaksies",
18012         "nds-nl"
18013     ],
18014     [
18015         "Nepali",
18016         "नेपाली",
18017         "ne"
18018     ],
18019     [
18020         "Newari",
18021         "नेपाल भाषा",
18022         "new"
18023     ],
18024     [
18025         "Dutch",
18026         "Nederlands",
18027         "nl"
18028     ],
18029     [
18030         "Norwegian Nynorsk",
18031         "norsk nynorsk",
18032         "nn"
18033     ],
18034     [
18035         "Norwegian",
18036         "norsk bokmål",
18037         "no"
18038     ],
18039     [
18040         "Novial",
18041         "Novial",
18042         "nov"
18043     ],
18044     [
18045         "Nouormand",
18046         "Nouormand",
18047         "nrm"
18048     ],
18049     [
18050         "Northern Sotho",
18051         "Sesotho sa Leboa",
18052         "nso"
18053     ],
18054     [
18055         "Navajo",
18056         "Diné bizaad",
18057         "nv"
18058     ],
18059     [
18060         "Nyanja",
18061         "Chi-Chewa",
18062         "ny"
18063     ],
18064     [
18065         "Occitan",
18066         "occitan",
18067         "oc"
18068     ],
18069     [
18070         "Livvi-Karelian",
18071         "Livvinкarjala",
18072         "olo"
18073     ],
18074     [
18075         "Oromo",
18076         "Oromoo",
18077         "om"
18078     ],
18079     [
18080         "Oriya",
18081         "ଓଡ଼ିଆ",
18082         "or"
18083     ],
18084     [
18085         "Ossetic",
18086         "Ирон",
18087         "os"
18088     ],
18089     [
18090         "Punjabi",
18091         "ਪੰਜਾਬੀ",
18092         "pa"
18093     ],
18094     [
18095         "Pangasinan",
18096         "Pangasinan",
18097         "pag"
18098     ],
18099     [
18100         "Pampanga",
18101         "Kapampangan",
18102         "pam"
18103     ],
18104     [
18105         "Papiamento",
18106         "Papiamentu",
18107         "pap"
18108     ],
18109     [
18110         "Picard",
18111         "Picard",
18112         "pcd"
18113     ],
18114     [
18115         "Pennsylvania German",
18116         "Deitsch",
18117         "pdc"
18118     ],
18119     [
18120         "Palatine German",
18121         "Pälzisch",
18122         "pfl"
18123     ],
18124     [
18125         "Pali",
18126         "पालि",
18127         "pi"
18128     ],
18129     [
18130         "Norfuk / Pitkern",
18131         "Norfuk / Pitkern",
18132         "pih"
18133     ],
18134     [
18135         "Polish",
18136         "polski",
18137         "pl"
18138     ],
18139     [
18140         "Piedmontese",
18141         "Piemontèis",
18142         "pms"
18143     ],
18144     [
18145         "Western Punjabi",
18146         "پنجابی",
18147         "pnb"
18148     ],
18149     [
18150         "Pontic",
18151         "Ποντιακά",
18152         "pnt"
18153     ],
18154     [
18155         "Pashto",
18156         "پښتو",
18157         "ps"
18158     ],
18159     [
18160         "Portuguese",
18161         "português",
18162         "pt"
18163     ],
18164     [
18165         "Quechua",
18166         "Runa Simi",
18167         "qu"
18168     ],
18169     [
18170         "Romansh",
18171         "rumantsch",
18172         "rm"
18173     ],
18174     [
18175         "Romani",
18176         "Romani",
18177         "rmy"
18178     ],
18179     [
18180         "Rundi",
18181         "Kirundi",
18182         "rn"
18183     ],
18184     [
18185         "Romanian",
18186         "română",
18187         "ro"
18188     ],
18189     [
18190         "Aromanian",
18191         "armãneashti",
18192         "roa-rup"
18193     ],
18194     [
18195         "tarandíne",
18196         "tarandíne",
18197         "roa-tara"
18198     ],
18199     [
18200         "Russian",
18201         "русский",
18202         "ru"
18203     ],
18204     [
18205         "Rusyn",
18206         "русиньскый",
18207         "rue"
18208     ],
18209     [
18210         "Kinyarwanda",
18211         "Kinyarwanda",
18212         "rw"
18213     ],
18214     [
18215         "Sanskrit",
18216         "संस्कृतम्",
18217         "sa"
18218     ],
18219     [
18220         "Sakha",
18221         "саха тыла",
18222         "sah"
18223     ],
18224     [
18225         "Sardinian",
18226         "sardu",
18227         "sc"
18228     ],
18229     [
18230         "Sicilian",
18231         "sicilianu",
18232         "scn"
18233     ],
18234     [
18235         "Scots",
18236         "Scots",
18237         "sco"
18238     ],
18239     [
18240         "Sindhi",
18241         "سنڌي",
18242         "sd"
18243     ],
18244     [
18245         "Northern Sami",
18246         "sámegiella",
18247         "se"
18248     ],
18249     [
18250         "Sango",
18251         "Sängö",
18252         "sg"
18253     ],
18254     [
18255         "Serbo-Croatian",
18256         "srpskohrvatski / српскохрватски",
18257         "sh"
18258     ],
18259     [
18260         "Sinhala",
18261         "සිංහල",
18262         "si"
18263     ],
18264     [
18265         "Simple English",
18266         "Simple English",
18267         "simple"
18268     ],
18269     [
18270         "Slovak",
18271         "slovenčina",
18272         "sk"
18273     ],
18274     [
18275         "Slovenian",
18276         "slovenščina",
18277         "sl"
18278     ],
18279     [
18280         "Samoan",
18281         "Gagana Samoa",
18282         "sm"
18283     ],
18284     [
18285         "Shona",
18286         "chiShona",
18287         "sn"
18288     ],
18289     [
18290         "Somali",
18291         "Soomaaliga",
18292         "so"
18293     ],
18294     [
18295         "Albanian",
18296         "shqip",
18297         "sq"
18298     ],
18299     [
18300         "Serbian",
18301         "српски / srpski",
18302         "sr"
18303     ],
18304     [
18305         "Sranan Tongo",
18306         "Sranantongo",
18307         "srn"
18308     ],
18309     [
18310         "Swati",
18311         "SiSwati",
18312         "ss"
18313     ],
18314     [
18315         "Southern Sotho",
18316         "Sesotho",
18317         "st"
18318     ],
18319     [
18320         "Saterland Frisian",
18321         "Seeltersk",
18322         "stq"
18323     ],
18324     [
18325         "Sundanese",
18326         "Basa Sunda",
18327         "su"
18328     ],
18329     [
18330         "Swedish",
18331         "svenska",
18332         "sv"
18333     ],
18334     [
18335         "Swahili",
18336         "Kiswahili",
18337         "sw"
18338     ],
18339     [
18340         "Silesian",
18341         "ślůnski",
18342         "szl"
18343     ],
18344     [
18345         "Tamil",
18346         "தமிழ்",
18347         "ta"
18348     ],
18349     [
18350         "Tulu",
18351         "ತುಳು",
18352         "tcy"
18353     ],
18354     [
18355         "Telugu",
18356         "తెలుగు",
18357         "te"
18358     ],
18359     [
18360         "Tetum",
18361         "tetun",
18362         "tet"
18363     ],
18364     [
18365         "Tajik",
18366         "тоҷикӣ",
18367         "tg"
18368     ],
18369     [
18370         "Thai",
18371         "ไทย",
18372         "th"
18373     ],
18374     [
18375         "Tigrinya",
18376         "ትግርኛ",
18377         "ti"
18378     ],
18379     [
18380         "Turkmen",
18381         "Türkmençe",
18382         "tk"
18383     ],
18384     [
18385         "Tagalog",
18386         "Tagalog",
18387         "tl"
18388     ],
18389     [
18390         "Tswana",
18391         "Setswana",
18392         "tn"
18393     ],
18394     [
18395         "Tongan",
18396         "lea faka-Tonga",
18397         "to"
18398     ],
18399     [
18400         "Tok Pisin",
18401         "Tok Pisin",
18402         "tpi"
18403     ],
18404     [
18405         "Turkish",
18406         "Türkçe",
18407         "tr"
18408     ],
18409     [
18410         "Tsonga",
18411         "Xitsonga",
18412         "ts"
18413     ],
18414     [
18415         "Tatar",
18416         "татарча/tatarça",
18417         "tt"
18418     ],
18419     [
18420         "Tumbuka",
18421         "chiTumbuka",
18422         "tum"
18423     ],
18424     [
18425         "Twi",
18426         "Twi",
18427         "tw"
18428     ],
18429     [
18430         "Tahitian",
18431         "reo tahiti",
18432         "ty"
18433     ],
18434     [
18435         "Tuvinian",
18436         "тыва дыл",
18437         "tyv"
18438     ],
18439     [
18440         "Udmurt",
18441         "удмурт",
18442         "udm"
18443     ],
18444     [
18445         "Uyghur",
18446         "ئۇيغۇرچە / Uyghurche",
18447         "ug"
18448     ],
18449     [
18450         "Ukrainian",
18451         "українська",
18452         "uk"
18453     ],
18454     [
18455         "Urdu",
18456         "اردو",
18457         "ur"
18458     ],
18459     [
18460         "Uzbek",
18461         "oʻzbekcha/ўзбекча",
18462         "uz"
18463     ],
18464     [
18465         "Venda",
18466         "Tshivenda",
18467         "ve"
18468     ],
18469     [
18470         "Venetian",
18471         "vèneto",
18472         "vec"
18473     ],
18474     [
18475         "Veps",
18476         "vepsän kel’",
18477         "vep"
18478     ],
18479     [
18480         "Vietnamese",
18481         "Tiếng Việt",
18482         "vi"
18483     ],
18484     [
18485         "West Flemish",
18486         "West-Vlams",
18487         "vls"
18488     ],
18489     [
18490         "Volapük",
18491         "Volapük",
18492         "vo"
18493     ],
18494     [
18495         "Walloon",
18496         "walon",
18497         "wa"
18498     ],
18499     [
18500         "Waray",
18501         "Winaray",
18502         "war"
18503     ],
18504     [
18505         "Wolof",
18506         "Wolof",
18507         "wo"
18508     ],
18509     [
18510         "Wu Chinese",
18511         "吴语",
18512         "wuu"
18513     ],
18514     [
18515         "Kalmyk",
18516         "хальмг",
18517         "xal"
18518     ],
18519     [
18520         "Xhosa",
18521         "isiXhosa",
18522         "xh"
18523     ],
18524     [
18525         "Mingrelian",
18526         "მარგალური",
18527         "xmf"
18528     ],
18529     [
18530         "Yiddish",
18531         "ייִדיש",
18532         "yi"
18533     ],
18534     [
18535         "Yoruba",
18536         "Yorùbá",
18537         "yo"
18538     ],
18539     [
18540         "Zhuang",
18541         "Vahcuengh",
18542         "za"
18543     ],
18544     [
18545         "Zeelandic",
18546         "Zeêuws",
18547         "zea"
18548     ],
18549     [
18550         "Chinese",
18551         "中文",
18552         "zh"
18553     ],
18554     [
18555         "Classical Chinese",
18556         "文言",
18557         "zh-classical"
18558     ],
18559     [
18560         "Chinese (Min Nan)",
18561         "Bân-lâm-gú",
18562         "zh-min-nan"
18563     ],
18564     [
18565         "Cantonese",
18566         "粵語",
18567         "zh-yue"
18568     ],
18569     [
18570         "Zulu",
18571         "isiZulu",
18572         "zu"
18573     ]
18574 ];
18575
18576 var dataFeatureIcons =  {
18577         "circle-stroked-24": {"x":0,"y":0,"width":24,"height":24},
18578         "circle-stroked-18": {"x":24,"y":0,"width":18,"height":18},
18579         "circle-stroked-12": {"x":42,"y":0,"width":12,"height":12},
18580         "circle-24": {"x":54,"y":0,"width":24,"height":24},
18581         "circle-18": {"x":78,"y":0,"width":18,"height":18},
18582         "circle-12": {"x":96,"y":0,"width":12,"height":12},
18583         "square-stroked-24": {"x":108,"y":0,"width":24,"height":24},
18584         "square-stroked-18": {"x":132,"y":0,"width":18,"height":18},
18585         "square-stroked-12": {"x":150,"y":0,"width":12,"height":12},
18586         "square-24": {"x":162,"y":0,"width":24,"height":24},
18587         "square-18": {"x":186,"y":0,"width":18,"height":18},
18588         "square-12": {"x":204,"y":0,"width":12,"height":12},
18589         "triangle-stroked-24": {"x":216,"y":0,"width":24,"height":24},
18590         "triangle-stroked-18": {"x":240,"y":0,"width":18,"height":18},
18591         "triangle-stroked-12": {"x":258,"y":0,"width":12,"height":12},
18592         "triangle-24": {"x":0,"y":24,"width":24,"height":24},
18593         "triangle-18": {"x":24,"y":24,"width":18,"height":18},
18594         "triangle-12": {"x":42,"y":24,"width":12,"height":12},
18595         "star-stroked-24": {"x":54,"y":24,"width":24,"height":24},
18596         "star-stroked-18": {"x":78,"y":24,"width":18,"height":18},
18597         "star-stroked-12": {"x":96,"y":24,"width":12,"height":12},
18598         "star-24": {"x":108,"y":24,"width":24,"height":24},
18599         "star-18": {"x":132,"y":24,"width":18,"height":18},
18600         "star-12": {"x":150,"y":24,"width":12,"height":12},
18601         "cross-24": {"x":162,"y":24,"width":24,"height":24},
18602         "cross-18": {"x":186,"y":24,"width":18,"height":18},
18603         "cross-12": {"x":204,"y":24,"width":12,"height":12},
18604         "marker-stroked-24": {"x":216,"y":24,"width":24,"height":24},
18605         "marker-stroked-18": {"x":240,"y":24,"width":18,"height":18},
18606         "marker-stroked-12": {"x":258,"y":24,"width":12,"height":12},
18607         "marker-24": {"x":0,"y":48,"width":24,"height":24},
18608         "marker-18": {"x":24,"y":48,"width":18,"height":18},
18609         "marker-12": {"x":42,"y":48,"width":12,"height":12},
18610         "religious-jewish-24": {"x":54,"y":48,"width":24,"height":24},
18611         "religious-jewish-18": {"x":78,"y":48,"width":18,"height":18},
18612         "religious-jewish-12": {"x":96,"y":48,"width":12,"height":12},
18613         "religious-christian-24": {"x":108,"y":48,"width":24,"height":24},
18614         "religious-christian-18": {"x":132,"y":48,"width":18,"height":18},
18615         "religious-christian-12": {"x":150,"y":48,"width":12,"height":12},
18616         "religious-muslim-24": {"x":162,"y":48,"width":24,"height":24},
18617         "religious-muslim-18": {"x":186,"y":48,"width":18,"height":18},
18618         "religious-muslim-12": {"x":204,"y":48,"width":12,"height":12},
18619         "cemetery-24": {"x":216,"y":48,"width":24,"height":24},
18620         "cemetery-18": {"x":240,"y":48,"width":18,"height":18},
18621         "cemetery-12": {"x":258,"y":48,"width":12,"height":12},
18622         "rocket-24": {"x":0,"y":72,"width":24,"height":24},
18623         "rocket-18": {"x":24,"y":72,"width":18,"height":18},
18624         "rocket-12": {"x":42,"y":72,"width":12,"height":12},
18625         "airport-24": {"x":54,"y":72,"width":24,"height":24},
18626         "airport-18": {"x":78,"y":72,"width":18,"height":18},
18627         "airport-12": {"x":96,"y":72,"width":12,"height":12},
18628         "heliport-24": {"x":108,"y":72,"width":24,"height":24},
18629         "heliport-18": {"x":132,"y":72,"width":18,"height":18},
18630         "heliport-12": {"x":150,"y":72,"width":12,"height":12},
18631         "rail-24": {"x":162,"y":72,"width":24,"height":24},
18632         "rail-18": {"x":186,"y":72,"width":18,"height":18},
18633         "rail-12": {"x":204,"y":72,"width":12,"height":12},
18634         "rail-metro-24": {"x":216,"y":72,"width":24,"height":24},
18635         "rail-metro-18": {"x":240,"y":72,"width":18,"height":18},
18636         "rail-metro-12": {"x":258,"y":72,"width":12,"height":12},
18637         "rail-light-24": {"x":0,"y":96,"width":24,"height":24},
18638         "rail-light-18": {"x":24,"y":96,"width":18,"height":18},
18639         "rail-light-12": {"x":42,"y":96,"width":12,"height":12},
18640         "bus-24": {"x":54,"y":96,"width":24,"height":24},
18641         "bus-18": {"x":78,"y":96,"width":18,"height":18},
18642         "bus-12": {"x":96,"y":96,"width":12,"height":12},
18643         "fuel-24": {"x":108,"y":96,"width":24,"height":24},
18644         "fuel-18": {"x":132,"y":96,"width":18,"height":18},
18645         "fuel-12": {"x":150,"y":96,"width":12,"height":12},
18646         "parking-24": {"x":162,"y":96,"width":24,"height":24},
18647         "parking-18": {"x":186,"y":96,"width":18,"height":18},
18648         "parking-12": {"x":204,"y":96,"width":12,"height":12},
18649         "parking-garage-24": {"x":216,"y":96,"width":24,"height":24},
18650         "parking-garage-18": {"x":240,"y":96,"width":18,"height":18},
18651         "parking-garage-12": {"x":258,"y":96,"width":12,"height":12},
18652         "airfield-24": {"x":0,"y":120,"width":24,"height":24},
18653         "airfield-18": {"x":24,"y":120,"width":18,"height":18},
18654         "airfield-12": {"x":42,"y":120,"width":12,"height":12},
18655         "roadblock-24": {"x":54,"y":120,"width":24,"height":24},
18656         "roadblock-18": {"x":78,"y":120,"width":18,"height":18},
18657         "roadblock-12": {"x":96,"y":120,"width":12,"height":12},
18658         "ferry-24": {"x":108,"y":120,"width":24,"height":24},
18659         "ferry-18": {"x":132,"y":120,"width":18,"height":18},
18660         "ferry-12": {"x":150,"y":120,"width":12,"height":12},
18661         "harbor-24": {"x":162,"y":120,"width":24,"height":24},
18662         "harbor-18": {"x":186,"y":120,"width":18,"height":18},
18663         "harbor-12": {"x":204,"y":120,"width":12,"height":12},
18664         "bicycle-24": {"x":216,"y":120,"width":24,"height":24},
18665         "bicycle-18": {"x":240,"y":120,"width":18,"height":18},
18666         "bicycle-12": {"x":258,"y":120,"width":12,"height":12},
18667         "park-24": {"x":0,"y":144,"width":24,"height":24},
18668         "park-18": {"x":24,"y":144,"width":18,"height":18},
18669         "park-12": {"x":42,"y":144,"width":12,"height":12},
18670         "park2-24": {"x":54,"y":144,"width":24,"height":24},
18671         "park2-18": {"x":78,"y":144,"width":18,"height":18},
18672         "park2-12": {"x":96,"y":144,"width":12,"height":12},
18673         "museum-24": {"x":108,"y":144,"width":24,"height":24},
18674         "museum-18": {"x":132,"y":144,"width":18,"height":18},
18675         "museum-12": {"x":150,"y":144,"width":12,"height":12},
18676         "lodging-24": {"x":162,"y":144,"width":24,"height":24},
18677         "lodging-18": {"x":186,"y":144,"width":18,"height":18},
18678         "lodging-12": {"x":204,"y":144,"width":12,"height":12},
18679         "monument-24": {"x":216,"y":144,"width":24,"height":24},
18680         "monument-18": {"x":240,"y":144,"width":18,"height":18},
18681         "monument-12": {"x":258,"y":144,"width":12,"height":12},
18682         "zoo-24": {"x":0,"y":168,"width":24,"height":24},
18683         "zoo-18": {"x":24,"y":168,"width":18,"height":18},
18684         "zoo-12": {"x":42,"y":168,"width":12,"height":12},
18685         "garden-24": {"x":54,"y":168,"width":24,"height":24},
18686         "garden-18": {"x":78,"y":168,"width":18,"height":18},
18687         "garden-12": {"x":96,"y":168,"width":12,"height":12},
18688         "campsite-24": {"x":108,"y":168,"width":24,"height":24},
18689         "campsite-18": {"x":132,"y":168,"width":18,"height":18},
18690         "campsite-12": {"x":150,"y":168,"width":12,"height":12},
18691         "theatre-24": {"x":162,"y":168,"width":24,"height":24},
18692         "theatre-18": {"x":186,"y":168,"width":18,"height":18},
18693         "theatre-12": {"x":204,"y":168,"width":12,"height":12},
18694         "art-gallery-24": {"x":216,"y":168,"width":24,"height":24},
18695         "art-gallery-18": {"x":240,"y":168,"width":18,"height":18},
18696         "art-gallery-12": {"x":258,"y":168,"width":12,"height":12},
18697         "pitch-24": {"x":0,"y":192,"width":24,"height":24},
18698         "pitch-18": {"x":24,"y":192,"width":18,"height":18},
18699         "pitch-12": {"x":42,"y":192,"width":12,"height":12},
18700         "soccer-24": {"x":54,"y":192,"width":24,"height":24},
18701         "soccer-18": {"x":78,"y":192,"width":18,"height":18},
18702         "soccer-12": {"x":96,"y":192,"width":12,"height":12},
18703         "america-football-24": {"x":108,"y":192,"width":24,"height":24},
18704         "america-football-18": {"x":132,"y":192,"width":18,"height":18},
18705         "america-football-12": {"x":150,"y":192,"width":12,"height":12},
18706         "tennis-24": {"x":162,"y":192,"width":24,"height":24},
18707         "tennis-18": {"x":186,"y":192,"width":18,"height":18},
18708         "tennis-12": {"x":204,"y":192,"width":12,"height":12},
18709         "basketball-24": {"x":216,"y":192,"width":24,"height":24},
18710         "basketball-18": {"x":240,"y":192,"width":18,"height":18},
18711         "basketball-12": {"x":258,"y":192,"width":12,"height":12},
18712         "baseball-24": {"x":0,"y":216,"width":24,"height":24},
18713         "baseball-18": {"x":24,"y":216,"width":18,"height":18},
18714         "baseball-12": {"x":42,"y":216,"width":12,"height":12},
18715         "golf-24": {"x":54,"y":216,"width":24,"height":24},
18716         "golf-18": {"x":78,"y":216,"width":18,"height":18},
18717         "golf-12": {"x":96,"y":216,"width":12,"height":12},
18718         "swimming-24": {"x":108,"y":216,"width":24,"height":24},
18719         "swimming-18": {"x":132,"y":216,"width":18,"height":18},
18720         "swimming-12": {"x":150,"y":216,"width":12,"height":12},
18721         "cricket-24": {"x":162,"y":216,"width":24,"height":24},
18722         "cricket-18": {"x":186,"y":216,"width":18,"height":18},
18723         "cricket-12": {"x":204,"y":216,"width":12,"height":12},
18724         "skiing-24": {"x":216,"y":216,"width":24,"height":24},
18725         "skiing-18": {"x":240,"y":216,"width":18,"height":18},
18726         "skiing-12": {"x":258,"y":216,"width":12,"height":12},
18727         "school-24": {"x":0,"y":240,"width":24,"height":24},
18728         "school-18": {"x":24,"y":240,"width":18,"height":18},
18729         "school-12": {"x":42,"y":240,"width":12,"height":12},
18730         "college-24": {"x":54,"y":240,"width":24,"height":24},
18731         "college-18": {"x":78,"y":240,"width":18,"height":18},
18732         "college-12": {"x":96,"y":240,"width":12,"height":12},
18733         "library-24": {"x":108,"y":240,"width":24,"height":24},
18734         "library-18": {"x":132,"y":240,"width":18,"height":18},
18735         "library-12": {"x":150,"y":240,"width":12,"height":12},
18736         "post-24": {"x":162,"y":240,"width":24,"height":24},
18737         "post-18": {"x":186,"y":240,"width":18,"height":18},
18738         "post-12": {"x":204,"y":240,"width":12,"height":12},
18739         "fire-station-24": {"x":216,"y":240,"width":24,"height":24},
18740         "fire-station-18": {"x":240,"y":240,"width":18,"height":18},
18741         "fire-station-12": {"x":258,"y":240,"width":12,"height":12},
18742         "town-hall-24": {"x":0,"y":264,"width":24,"height":24},
18743         "town-hall-18": {"x":24,"y":264,"width":18,"height":18},
18744         "town-hall-12": {"x":42,"y":264,"width":12,"height":12},
18745         "police-24": {"x":54,"y":264,"width":24,"height":24},
18746         "police-18": {"x":78,"y":264,"width":18,"height":18},
18747         "police-12": {"x":96,"y":264,"width":12,"height":12},
18748         "prison-24": {"x":108,"y":264,"width":24,"height":24},
18749         "prison-18": {"x":132,"y":264,"width":18,"height":18},
18750         "prison-12": {"x":150,"y":264,"width":12,"height":12},
18751         "embassy-24": {"x":162,"y":264,"width":24,"height":24},
18752         "embassy-18": {"x":186,"y":264,"width":18,"height":18},
18753         "embassy-12": {"x":204,"y":264,"width":12,"height":12},
18754         "beer-24": {"x":216,"y":264,"width":24,"height":24},
18755         "beer-18": {"x":240,"y":264,"width":18,"height":18},
18756         "beer-12": {"x":258,"y":264,"width":12,"height":12},
18757         "restaurant-24": {"x":0,"y":288,"width":24,"height":24},
18758         "restaurant-18": {"x":24,"y":288,"width":18,"height":18},
18759         "restaurant-12": {"x":42,"y":288,"width":12,"height":12},
18760         "cafe-24": {"x":54,"y":288,"width":24,"height":24},
18761         "cafe-18": {"x":78,"y":288,"width":18,"height":18},
18762         "cafe-12": {"x":96,"y":288,"width":12,"height":12},
18763         "shop-24": {"x":108,"y":288,"width":24,"height":24},
18764         "shop-18": {"x":132,"y":288,"width":18,"height":18},
18765         "shop-12": {"x":150,"y":288,"width":12,"height":12},
18766         "fast-food-24": {"x":162,"y":288,"width":24,"height":24},
18767         "fast-food-18": {"x":186,"y":288,"width":18,"height":18},
18768         "fast-food-12": {"x":204,"y":288,"width":12,"height":12},
18769         "bar-24": {"x":216,"y":288,"width":24,"height":24},
18770         "bar-18": {"x":240,"y":288,"width":18,"height":18},
18771         "bar-12": {"x":258,"y":288,"width":12,"height":12},
18772         "bank-24": {"x":0,"y":312,"width":24,"height":24},
18773         "bank-18": {"x":24,"y":312,"width":18,"height":18},
18774         "bank-12": {"x":42,"y":312,"width":12,"height":12},
18775         "grocery-24": {"x":54,"y":312,"width":24,"height":24},
18776         "grocery-18": {"x":78,"y":312,"width":18,"height":18},
18777         "grocery-12": {"x":96,"y":312,"width":12,"height":12},
18778         "cinema-24": {"x":108,"y":312,"width":24,"height":24},
18779         "cinema-18": {"x":132,"y":312,"width":18,"height":18},
18780         "cinema-12": {"x":150,"y":312,"width":12,"height":12},
18781         "pharmacy-24": {"x":162,"y":312,"width":24,"height":24},
18782         "pharmacy-18": {"x":186,"y":312,"width":18,"height":18},
18783         "pharmacy-12": {"x":204,"y":312,"width":12,"height":12},
18784         "hospital-24": {"x":216,"y":312,"width":24,"height":24},
18785         "hospital-18": {"x":240,"y":312,"width":18,"height":18},
18786         "hospital-12": {"x":258,"y":312,"width":12,"height":12},
18787         "danger-24": {"x":0,"y":336,"width":24,"height":24},
18788         "danger-18": {"x":24,"y":336,"width":18,"height":18},
18789         "danger-12": {"x":42,"y":336,"width":12,"height":12},
18790         "industrial-24": {"x":54,"y":336,"width":24,"height":24},
18791         "industrial-18": {"x":78,"y":336,"width":18,"height":18},
18792         "industrial-12": {"x":96,"y":336,"width":12,"height":12},
18793         "warehouse-24": {"x":108,"y":336,"width":24,"height":24},
18794         "warehouse-18": {"x":132,"y":336,"width":18,"height":18},
18795         "warehouse-12": {"x":150,"y":336,"width":12,"height":12},
18796         "commercial-24": {"x":162,"y":336,"width":24,"height":24},
18797         "commercial-18": {"x":186,"y":336,"width":18,"height":18},
18798         "commercial-12": {"x":204,"y":336,"width":12,"height":12},
18799         "building-24": {"x":216,"y":336,"width":24,"height":24},
18800         "building-18": {"x":240,"y":336,"width":18,"height":18},
18801         "building-12": {"x":258,"y":336,"width":12,"height":12},
18802         "place-of-worship-24": {"x":0,"y":360,"width":24,"height":24},
18803         "place-of-worship-18": {"x":24,"y":360,"width":18,"height":18},
18804         "place-of-worship-12": {"x":42,"y":360,"width":12,"height":12},
18805         "alcohol-shop-24": {"x":54,"y":360,"width":24,"height":24},
18806         "alcohol-shop-18": {"x":78,"y":360,"width":18,"height":18},
18807         "alcohol-shop-12": {"x":96,"y":360,"width":12,"height":12},
18808         "logging-24": {"x":108,"y":360,"width":24,"height":24},
18809         "logging-18": {"x":132,"y":360,"width":18,"height":18},
18810         "logging-12": {"x":150,"y":360,"width":12,"height":12},
18811         "oil-well-24": {"x":162,"y":360,"width":24,"height":24},
18812         "oil-well-18": {"x":186,"y":360,"width":18,"height":18},
18813         "oil-well-12": {"x":204,"y":360,"width":12,"height":12},
18814         "slaughterhouse-24": {"x":216,"y":360,"width":24,"height":24},
18815         "slaughterhouse-18": {"x":240,"y":360,"width":18,"height":18},
18816         "slaughterhouse-12": {"x":258,"y":360,"width":12,"height":12},
18817         "dam-24": {"x":0,"y":384,"width":24,"height":24},
18818         "dam-18": {"x":24,"y":384,"width":18,"height":18},
18819         "dam-12": {"x":42,"y":384,"width":12,"height":12},
18820         "water-24": {"x":54,"y":384,"width":24,"height":24},
18821         "water-18": {"x":78,"y":384,"width":18,"height":18},
18822         "water-12": {"x":96,"y":384,"width":12,"height":12},
18823         "wetland-24": {"x":108,"y":384,"width":24,"height":24},
18824         "wetland-18": {"x":132,"y":384,"width":18,"height":18},
18825         "wetland-12": {"x":150,"y":384,"width":12,"height":12},
18826         "disability-24": {"x":162,"y":384,"width":24,"height":24},
18827         "disability-18": {"x":186,"y":384,"width":18,"height":18},
18828         "disability-12": {"x":204,"y":384,"width":12,"height":12},
18829         "telephone-24": {"x":216,"y":384,"width":24,"height":24},
18830         "telephone-18": {"x":240,"y":384,"width":18,"height":18},
18831         "telephone-12": {"x":258,"y":384,"width":12,"height":12},
18832         "emergency-telephone-24": {"x":0,"y":408,"width":24,"height":24},
18833         "emergency-telephone-18": {"x":24,"y":408,"width":18,"height":18},
18834         "emergency-telephone-12": {"x":42,"y":408,"width":12,"height":12},
18835         "toilets-24": {"x":54,"y":408,"width":24,"height":24},
18836         "toilets-18": {"x":78,"y":408,"width":18,"height":18},
18837         "toilets-12": {"x":96,"y":408,"width":12,"height":12},
18838         "waste-basket-24": {"x":108,"y":408,"width":24,"height":24},
18839         "waste-basket-18": {"x":132,"y":408,"width":18,"height":18},
18840         "waste-basket-12": {"x":150,"y":408,"width":12,"height":12},
18841         "music-24": {"x":162,"y":408,"width":24,"height":24},
18842         "music-18": {"x":186,"y":408,"width":18,"height":18},
18843         "music-12": {"x":204,"y":408,"width":12,"height":12},
18844         "land-use-24": {"x":216,"y":408,"width":24,"height":24},
18845         "land-use-18": {"x":240,"y":408,"width":18,"height":18},
18846         "land-use-12": {"x":258,"y":408,"width":12,"height":12},
18847         "city-24": {"x":0,"y":432,"width":24,"height":24},
18848         "city-18": {"x":24,"y":432,"width":18,"height":18},
18849         "city-12": {"x":42,"y":432,"width":12,"height":12},
18850         "town-24": {"x":54,"y":432,"width":24,"height":24},
18851         "town-18": {"x":78,"y":432,"width":18,"height":18},
18852         "town-12": {"x":96,"y":432,"width":12,"height":12},
18853         "village-24": {"x":108,"y":432,"width":24,"height":24},
18854         "village-18": {"x":132,"y":432,"width":18,"height":18},
18855         "village-12": {"x":150,"y":432,"width":12,"height":12},
18856         "farm-24": {"x":162,"y":432,"width":24,"height":24},
18857         "farm-18": {"x":186,"y":432,"width":18,"height":18},
18858         "farm-12": {"x":204,"y":432,"width":12,"height":12},
18859         "bakery-24": {"x":216,"y":432,"width":24,"height":24},
18860         "bakery-18": {"x":240,"y":432,"width":18,"height":18},
18861         "bakery-12": {"x":258,"y":432,"width":12,"height":12},
18862         "dog-park-24": {"x":0,"y":456,"width":24,"height":24},
18863         "dog-park-18": {"x":24,"y":456,"width":18,"height":18},
18864         "dog-park-12": {"x":42,"y":456,"width":12,"height":12},
18865         "lighthouse-24": {"x":54,"y":456,"width":24,"height":24},
18866         "lighthouse-18": {"x":78,"y":456,"width":18,"height":18},
18867         "lighthouse-12": {"x":96,"y":456,"width":12,"height":12},
18868         "clothing-store-24": {"x":108,"y":456,"width":24,"height":24},
18869         "clothing-store-18": {"x":132,"y":456,"width":18,"height":18},
18870         "clothing-store-12": {"x":150,"y":456,"width":12,"height":12},
18871         "polling-place-24": {"x":162,"y":456,"width":24,"height":24},
18872         "polling-place-18": {"x":186,"y":456,"width":18,"height":18},
18873         "polling-place-12": {"x":204,"y":456,"width":12,"height":12},
18874         "playground-24": {"x":216,"y":456,"width":24,"height":24},
18875         "playground-18": {"x":240,"y":456,"width":18,"height":18},
18876         "playground-12": {"x":258,"y":456,"width":12,"height":12},
18877         "entrance-24": {"x":0,"y":480,"width":24,"height":24},
18878         "entrance-18": {"x":24,"y":480,"width":18,"height":18},
18879         "entrance-12": {"x":42,"y":480,"width":12,"height":12},
18880         "heart-24": {"x":54,"y":480,"width":24,"height":24},
18881         "heart-18": {"x":78,"y":480,"width":18,"height":18},
18882         "heart-12": {"x":96,"y":480,"width":12,"height":12},
18883         "london-underground-24": {"x":108,"y":480,"width":24,"height":24},
18884         "london-underground-18": {"x":132,"y":480,"width":18,"height":18},
18885         "london-underground-12": {"x":150,"y":480,"width":12,"height":12},
18886         "minefield-24": {"x":162,"y":480,"width":24,"height":24},
18887         "minefield-18": {"x":186,"y":480,"width":18,"height":18},
18888         "minefield-12": {"x":204,"y":480,"width":12,"height":12},
18889         "rail-underground-24": {"x":216,"y":480,"width":24,"height":24},
18890         "rail-underground-18": {"x":240,"y":480,"width":18,"height":18},
18891         "rail-underground-12": {"x":258,"y":480,"width":12,"height":12},
18892         "rail-above-24": {"x":0,"y":504,"width":24,"height":24},
18893         "rail-above-18": {"x":24,"y":504,"width":18,"height":18},
18894         "rail-above-12": {"x":42,"y":504,"width":12,"height":12},
18895         "camera-24": {"x":54,"y":504,"width":24,"height":24},
18896         "camera-18": {"x":78,"y":504,"width":18,"height":18},
18897         "camera-12": {"x":96,"y":504,"width":12,"height":12},
18898         "laundry-24": {"x":108,"y":504,"width":24,"height":24},
18899         "laundry-18": {"x":132,"y":504,"width":18,"height":18},
18900         "laundry-12": {"x":150,"y":504,"width":12,"height":12},
18901         "car-24": {"x":162,"y":504,"width":24,"height":24},
18902         "car-18": {"x":186,"y":504,"width":18,"height":18},
18903         "car-12": {"x":204,"y":504,"width":12,"height":12},
18904         "suitcase-24": {"x":216,"y":504,"width":24,"height":24},
18905         "suitcase-18": {"x":240,"y":504,"width":18,"height":18},
18906         "suitcase-12": {"x":258,"y":504,"width":12,"height":12},
18907         "hairdresser-24": {"x":0,"y":528,"width":24,"height":24},
18908         "hairdresser-18": {"x":24,"y":528,"width":18,"height":18},
18909         "hairdresser-12": {"x":42,"y":528,"width":12,"height":12},
18910         "chemist-24": {"x":54,"y":528,"width":24,"height":24},
18911         "chemist-18": {"x":78,"y":528,"width":18,"height":18},
18912         "chemist-12": {"x":96,"y":528,"width":12,"height":12},
18913         "mobilephone-24": {"x":108,"y":528,"width":24,"height":24},
18914         "mobilephone-18": {"x":132,"y":528,"width":18,"height":18},
18915         "mobilephone-12": {"x":150,"y":528,"width":12,"height":12},
18916         "scooter-24": {"x":162,"y":528,"width":24,"height":24},
18917         "scooter-18": {"x":186,"y":528,"width":18,"height":18},
18918         "scooter-12": {"x":204,"y":528,"width":12,"height":12},
18919         "gift-24": {"x":216,"y":528,"width":24,"height":24},
18920         "gift-18": {"x":240,"y":528,"width":18,"height":18},
18921         "gift-12": {"x":258,"y":528,"width":12,"height":12},
18922         "ice-cream-24": {"x":0,"y":552,"width":24,"height":24},
18923         "ice-cream-18": {"x":24,"y":552,"width":18,"height":18},
18924         "ice-cream-12": {"x":42,"y":552,"width":12,"height":12}
18925 };
18926
18927 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}}};
18928 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}}};
18929 var dataSuggestions = {
18930         amenity: amenity,
18931         shop: shop
18932 };
18933
18934 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"]]}];
18935
18936 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"}}];
18937
18938 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"];
18939
18940 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"];
18941
18942 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"};
18943
18944 var type = "FeatureCollection";
18945 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]]]}}];
18946 var dataImperial = {
18947         type: type,
18948         features: features
18949 };
18950
18951 var type$1 = "FeatureCollection";
18952 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]]]}}];
18953 var dataDriveLeft = {
18954         type: type$1,
18955         features: features$1
18956 };
18957
18958 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 {zoom}, {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":""}}}};
18959
18960 var dataImagery = [{"id":"sjcgis.org-Aerials_2013_WM","name":"2013 aerial imagery for San Juan County WA","type":"tms","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/Aerials_2013_WM/MapServer/tile/{zoom}/{y}/{x}","description":"Public domain aerial imagery taken in May/June 2013 from San Juan County, WA. Resolution is 9 inch.","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},{"id":"OS7","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]]]},{"id":"AGRI-black_and_white-2.5m","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"},{"id":"basemap.at","name":"basemap.at","type":"tms","template":"https://maps{switch:1,2,3,4}.wien.gv.at/basemap/geolandbasemap/normal/google3857/{zoom}/{y}/{x}.png","description":"Basemap of Austria, based on goverment data.","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","name":"basemap.at Orthofoto","type":"tms","template":"https://maps{switch:1,2,3,4}.wien.gv.at/basemap/bmaporthofoto30cm/normal/google3857/{zoom}/{y}/{x}.jpeg","description":"Orthofoto layer provided by basemap.at. \"Successor\" of geoimage.at imagery.","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","best":true},{"id":"bavaria-DOP80","name":"Bavaria DOP 80cm","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/BAYERNDOP80/EPSG900913/{zoom}/{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]]]},{"id":"AGIV","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},{"id":"Benin_cotonou_pleiade_2016","name":"Benin: Cotonou Pleiade 2016","type":"tms","template":"http://geoxxx.agrocampus-ouest.fr/owsifl/gwc/service/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=Benin:cotonou_pleiade_2016&STYLE=&FORMAT=image/jpeg&tileMatrixSet=EPSG:3857&tileMatrix=EPSG:3857:{zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,21],"polygon":[[[2.31953818544,6.55745092536],[2.33645249928,6.56023631702],[2.36377172444,6.56211241002],[2.36737717181,6.56067658005],[2.37777373205,6.54939665325],[2.3777926612,6.53484752744],[2.36994151563,6.4933195729],[2.37038356708,6.45527010853],[2.36958186167,6.45269435578],[2.36188103586,6.44177160245],[2.35391742884,6.40545220189],[2.3674929737,6.40149524022],[2.39525870424,6.40071623744],[2.40128040262,6.40374371884],[2.40587684694,6.40340733291],[2.42045897749,6.39382909301],[2.42485054154,6.3979366042],[2.42949152505,6.39887495342],[2.43625257397,6.39628121034],[2.43958410532,6.40041525877],[2.44439433776,6.40189359345],[2.45375647532,6.39899446003],[2.47144744127,6.3963166199],[2.48162019208,6.3910582748],[2.49453210303,6.38739776192],[2.50893162289,6.38888498676],[2.50719014059,6.39228876781],[2.50120407357,6.39162040687],[2.4963025358,6.39521449649],[2.49509997769,6.40123077776],[2.49543290813,6.40400928653],[2.49830345887,6.41022131795],[2.50191336015,6.41281720321],[2.5108701911,6.41321333458],[2.52218648559,6.40849403999],[2.53352059576,6.4051656109],[2.53809922441,6.40960941297],[2.5411100736,6.41090182623],[2.54650822333,6.41099034757],[2.54654385468,6.40651114868],[2.57638511144,6.40723702943],[2.57642074279,6.41176933466],[2.58575615684,6.41196408125],[2.58867792765,6.41095493903],[2.60877400982,6.39413560832],[2.62569890171,6.39487921149],[2.64554556441,6.39728706193],[2.65039142819,6.39339200408],[2.6536650586,6.36823275735],[2.6431181786,6.3665949733],[2.61251084779,6.3628944474],[2.56867983171,6.3607044406],[2.54682890549,6.36055393954],[2.54687344468,6.35546343647],[2.50206702036,6.35461353888],[2.47064016846,6.35595920942],[2.46777184468,6.35202842507],[2.46422652522,6.35020467258],[2.45253944198,6.35006302163],[2.4511320036,6.34813302357],[2.44737289603,6.34629155079],[2.43757427441,6.34653944174],[2.43297783009,6.33841209773],[2.43016295333,6.33706638135],[2.42244876576,6.33706638135],[2.39236031651,6.34114999999],[2.39315311407,6.34114999999],[2.3652849434,6.34445228474],[2.35386064137,6.34529777247],[2.34377474198,6.34457844399],[2.34093759563,6.34533982549],[2.31086028117,6.36567095094],[2.28434610184,6.37465215648],[2.28146887022,6.37761782314],[2.27599054995,6.39517244756],[2.27611525968,6.39819996182],[2.31528747657,6.4926104105],[2.31579967725,6.5530659484]],[[1.69563043958,6.25076170066],[1.70009994721,6.24711901182],[1.70417862346,6.24697179839],[1.75874803806,6.25835802546],[1.77079143482,6.25995187823],[1.81712109941,6.27161341959],[1.84456614779,6.27656750346],[1.85767848509,6.27944518918],[1.88843363033,6.28325588467],[1.90481876292,6.28594870029],[1.90617692982,6.29435189983],[1.90083111364,6.29721233234],[1.89880903445,6.29953873942],[1.89404334121,6.30085024405],[1.89047742238,6.29969866569],[1.88747882146,6.29636150888],[1.88344050885,6.29622344016],[1.86969682855,6.29226563906],[1.8564007671,6.29198230539],[1.85206654725,6.28674503171],[1.84991419093,6.28906373821],[1.84691224958,6.29202989661],[1.8435272712,6.29332703219],[1.84040507404,6.29315437611],[1.83626738336,6.29129499924],[1.83409832485,6.28733273348],[1.83416513363,6.2851988527],[1.83229560117,6.28456355663],[1.82785949792,6.28644177291],[1.82182443779,6.2908379014],[1.81562903657,6.28997904337],[1.81211044063,6.29143113241],[1.80757635117,6.29570768815],[1.80471693522,6.29692955475],[1.80073513171,6.29709778253],[1.79775991387,6.29612383144],[1.79625448928,6.29491967121],[1.79490049792,6.28965143736],[1.79641483036,6.28608317469],[1.80097564333,6.28338261222],[1.79566657198,6.28013306439],[1.79156005874,6.28174455931],[1.78498607441,6.28122215216],[1.78092410036,6.27752986974],[1.77588226414,6.27550220232],[1.76744654171,6.27696318619],[1.75653444036,6.27496207997],[1.74833032171,6.27238985028],[1.74761769468,6.27726423691],[1.74572477914,6.27938486862],[1.73948038482,6.27984972411],[1.73680357955,6.27761398678],[1.73572127725,6.27891558552],[1.72901812928,6.27911038233],[1.72435487617,6.27422273126],[1.72449294765,6.2678607472],[1.72555966124,6.26683029328],[1.69933944056,6.26159387355],[1.69572953928,6.25725948175]]],"best":true},{"id":"Bing","name":"Bing aerial imagery","type":"bing","template":"http://www.bing.com/maps/","description":"Satellite and aerial imagery.","scaleExtent":[0,22],"default":true},{"id":"British_Columbia_Mosaic","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"},{"id":"osm-cambodia_laos_thailand_vietnam-bilingual","name":"Cambodia, Laos, Thailand, Vietnam, Myanmar bilingual","type":"tms","template":"http://{switch:a,b,c,d}.tile.osm-tools.org/osm_then/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"polygon":[[[92.1023798,20.8135629],[93.5690546,24.0975527],[94.1733026,23.9269484],[95.1950312,26.707274],[96.7550898,27.5286657],[97.5845575,28.5805966],[98.738122,27.514051],[98.7436151,25.8799151],[97.6779413,24.7577376],[97.9635858,24.042382],[98.8205194,24.1627239],[99.5236444,22.9593356],[100.3695917,21.5051376],[101.7923212,22.4830518],[105.3628778,23.3331079],[106.8185663,22.8480137],[108.1973505,21.3619661],[107.4389505,18.8539792],[117.1453714,7.4656173],[119.6172953,5.2875389],[118.1231546,4.0502277],[117.2552347,4.3624942],[115.8654642,4.3460623],[115.5084085,3.0249771],[114.552598,1.5100953],[113.5418558,1.2574836],[112.9650736,1.5704982],[112.2454691,1.5100953],[111.67418,1.0158321],[110.4546976,0.9004918],[109.4988871,1.9218969],[103.2256937,1.1256762],[100.4626322,3.2388904],[97.6721048,8.0588831],[93.892808,15.9398659],[92.1023798,20.8135629]]],"terms_url":"http://www.osm-tools.org/","terms_text":"© osm-tools.org & OpenStreetMap contributors, CC-BY-SA"},{"id":"South_Africa-CapeTown-Aerial-2013","name":"City of Cape Town 2013 Aerial","type":"tms","template":"http://{switch:a,b,c}.coct.aerial.openstreetmap.org.za/layer/za_coct_aerial_2013/{zoom}/{x}/{y}.jpg","description":"OpenStreetMap use only. City of Cape Town Aerial ortho-photography of the municipal area. 12cm ground sample distance","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"},{"id":"South_Africa-CapeTown-Aerial","name":"City of Cape Town 2015 Aerial","type":"tms","template":"http://{switch:a,b,c}.coct.aerial.openstreetmap.org.za/layer/za_coct_aerial_2015/{zoom}/{x}/{y}.jpg","description":"OpenStreetMap use only. City of Cape Town Aerial ortho-photography of the municipal area. 8cm ground sample distance","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},{"id":"Czech_CUZK-KM-tms","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},{"id":"Czech_RUIAN-budovy","name":"Czech RUIAN budovy","type":"tms","template":"http://tile.poloha.net/budovy/{zoom}/{x}/{y}.png","scaleExtent":[12,20],"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]]],"terms_url":"http://poloha.net/"},{"id":"Czech_RUIAN-parcely","name":"Czech RUIAN parcely","type":"tms","template":"http://tile.poloha.net/parcely/{zoom}/{x}/{y}.png","scaleExtent":[12,20],"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]]],"terms_url":"http://poloha.net/"},{"id":"Duna_2013","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"},{"id":"Delaware2012Orthophotography","name":"Delaware 2012 Orthophotography","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/0/https://firstmap.delaware.gov/arcgis/services/DE_Imagery/DE_Imagery_2012/ImageServer/WMSServer","description":"This data set consists of 0.3-meter pixel resolution (approximately 1-foot), 4-band true color and near infrared (R, G, B, IR) orthoimages covering New Castle, Kent and Sussex Counties in Delaware.","polygon":[[[-75.01770587603,38.45188674427],[-75.74173524589,38.4499581145],[-75.80699639658,39.73907123636],[-75.75558784863,39.80106251053],[-75.64692187603,39.8563815616],[-75.47114773904,39.84645578141],[-75.37725787603,39.81477822231],[-75.48746302671,39.6718115509],[-75.50901151986,39.43446011595],[-75.39326532808,39.27784018498],[-75.30707135548,39.01666513594],[-75.1931721774,38.82218696272],[-75.05341480753,38.80875503297],[-75.01770587603,38.45188674427]]]},{"id":"maaamet.ee-orto","name":"Estonia Ortho (Maaamet)","type":"tms","template":"http://kaart.maakaart.ee/orto/{zoom}/{x}/{y}.jpeg","scaleExtent":[14,20],"polygon":[[[21.6940073,57.5025466],[21.6940073,59.8274564],[28.2110546,59.8274564],[28.2110546,57.5025466],[21.6940073,57.5025466]]],"terms_text":"Maa-Ameti ortofoto "},{"id":"FOMI_2000","name":"FÖMI ortofotó 2000","type":"tms","template":"http://e.tile.openstreetmap.hu/ortofoto2000/{zoom}/{x}/{y}.jpg","description":"Hungary","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"},{"id":"FOMI_2005","name":"FÖMI ortofotó 2005","type":"tms","template":"http://e.tile.openstreetmap.hu/ortofoto2005/{zoom}/{x}/{y}.jpg","description":"Hungary","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"},{"id":"FR-BAN","name":"FR-BAN","type":"tms","template":"http://{switch:a,b,c}.layers.openstreetmap.fr/bano/{zoom}/{x}/{y}.png","description":"French address registry or Base Adresses Nationale","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-Cadastre","name":"FR-Cadastre","type":"tms","template":"http://tms.cadastre.openstreetmap.fr/*/tout/{zoom}/{x}/{y}.png","description":"French land registry","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":"Freemap.sk-Car","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."},{"id":"Freemap.sk-Cyclo","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."},{"id":"Freemap.sk-Hiking","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."},{"id":"Freemap.sk-Ski","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."},{"id":"Geodatastyrelsen_Denmark","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},{"id":"Geoportal-PL-aerial_image","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},{"id":"IBGE_DF_Addresses","name":"IBGE Distrito Federal","type":"tms","template":"https://api.mapbox.com/styles/v1/wille/cirnnxni1000jg8nfppc8g7pm/tiles/256/{zoom}/{x}/{y}?access_token=pk.eyJ1Ijoid2lsbGUiLCJhIjoicFNVWk5VWSJ9.hluCd0YGvYHNlFi_utWe2g","description":"Addresses data from IBGE","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},{"id":"IBGE_Setores_Rurais","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]]]},{"id":"IBGE_Setores_Urbanos","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]]]},{"id":"Haiti-Drone","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]]]},{"id":"osmim-imagicode-LC80700162014211LGN00","name":"imagico.de OSM images for mapping: Alaska Range","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80700162014211LGN00&z={zoom}&x={x}&y={-y}","description":"LC80700162014211LGN00, 2014-07-31 channels 234 (true color), Recent summer image of the Alaska Range for mapping natural features","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-LC81190582014075LGN00","name":"imagico.de OSM images for mapping: Bakun Reservoir","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81190582014075LGN00&z={zoom}&x={x}&y={-y}","description":"LC81190582014075LGN00/LC81180582015183LGN00, 2014-03-16, channels 234 (true color), Missing in older pre-2011 images","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-LC81250592016107LGN00","name":"imagico.de OSM images for mapping: Batam","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81250592016107LGN00&z={zoom}&x={x}&y={-y}","description":"LC81250592016107LGN00, LC81250602015184LGN00, LC81240602014174LGN00, 2014-2016, channels 234 (true color), Missing Islands in OSM","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-LC81800982013291LGN00","name":"imagico.de OSM images for mapping: Bouvet Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81800982013291LGN00&z={zoom}&x={x}&y={-y}","description":"LC81800982013291LGN00, 2013-10-18, channels 234 (true color), For more accurate coastline and glacier mapping","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","best":true},{"id":"osmim-imagicode-LC82050982015344LGN00","name":"imagico.de OSM images for mapping: Clerke Rocks","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82050982015344LGN00&z={zoom}&x={x}&y={-y}","description":"LC82050982015344LGN00, 2015-12-10, channels 234 (true color), Missing in other image sources","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-S2A_R022_N06_20151221T103009","name":"imagico.de OSM images for mapping: Cotonou","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R022_N06_20151221T103009&z={zoom}&x={x}&y={-y}","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","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-LC80360072014245LGN00","name":"imagico.de OSM images for mapping: Eastern Devon Island coast","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80360072014245LGN00&z={zoom}&x={x}&y={-y}","description":"LC80360072014245LGN00/LC80380062014243LGN00, 2014-09-02, channel 654 (false color IR), Coastline mostly mapped meanwhile","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-LC82160152013239LGN00","name":"imagico.de OSM images for mapping: Eastern Iceland","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82160152013239LGN00&z={zoom}&x={x}&y={-y}","description":"LC82160152013239LGN00, 2013-08-27, channels 234 (true color), Missing islets and inaccurate coast","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-AST_L1T_00302052007154424_20150518041444_91492","name":"imagico.de OSM images for mapping: El Altar","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=AST_L1T_00302052007154424_20150518041444_91492&z={zoom}&x={x}&y={-y}","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","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-S2A_R009_S61_20160109","name":"imagico.de OSM images for mapping: Elephant Island/Clarence Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R009_S61_20160109&z={zoom}&x={x}&y={-y}","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","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-LC82100502015347LGN00","name":"imagico.de OSM images for mapping: Fogo, Cape Verde","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82100502015347LGN00&z={zoom}&x={x}&y={-y}","description":"LC82100502015347LGN00, 2015-12-13, channels 234 (true color), Image from after the 2014/2015 eruption","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-greenland","name":"imagico.de OSM images for mapping: Greenland mosaic","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=greenland&z={zoom}&x={x}&y={-y}","description":"mostly Landsat 8 2013-2015 channels 234 (true color), Landsat mosaic of Greenland","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-S2A_R047_S54_20160411T044330","name":"imagico.de OSM images for mapping: Heard Island coast","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R047_S54_20160411T044330&z={zoom}&x={x}&y={-y}","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","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-LC82280982013259LGN00","name":"imagico.de OSM images for mapping: Isla Londonderry","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82280982013259LGN00&z={zoom}&x={x}&y={-y}","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","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-AST_L1T_00311162013112731_20150618142416_109190","name":"imagico.de OSM images for mapping: Leskov Island ASTER","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=AST_L1T_00311162013112731_20150618142416_109190&z={zoom}&x={x}&y={-y}","description":"AST_L1T_00311162013112731_20150618142416_109190, 2013-11-16, channels 12x (true color with estimated blue), Missing in other image sources","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-LC81991002015286LGN00","name":"imagico.de OSM images for mapping: Leskov Island Landsat","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81991002015286LGN00&z={zoom}&x={x}&y={-y}","description":"LC81991002015286LGN00, 2015-10-13, channels 234 (true color), Missing in other image sources","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-ls_polar","name":"imagico.de OSM images for mapping: May 2013 off-nadir Landsat","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ls_polar&z={zoom}&x={x}&y={-y}","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","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-LC80940622015159LGN00","name":"imagico.de OSM images for mapping: New Ireland","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80940622015159LGN00&z={zoom}&x={x}&y={-y}","description":"LC80940622015159LGN00, 2015-06-08, channels 234 (true color), Many missing islands in OSM (mostly mapped meanwhile)","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-nellesmere_ast","name":"imagico.de OSM images for mapping: Northern Ellesmere Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=nellesmere_ast&z={zoom}&x={x}&y={-y}","description":"ASTER L1T, 2012-07-09/2012-07-15, channels 12x (true color with estimated blue), Assembled from July 2012 ASTER imagery","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-LC81960222015233LGN00vis","name":"imagico.de OSM images for mapping: Northern German west coast tidalflats","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81960222015233LGN00vis&z={zoom}&x={x}&y={-y}","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","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 German west coast tidalflats (infrared)","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81960222015233LGN00ir&z={zoom}&x={x}&y={-y}","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","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-ngreenland_ast","name":"imagico.de OSM images for mapping: Northern Greenland ASTER","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=ngreenland_ast&z={zoom}&x={x}&y={-y}","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","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-EO1A1350972013086110KF","name":"imagico.de OSM images for mapping: Northwest Heard Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=EO1A1350972013086110KF&z={zoom}&x={x}&y={-y}","description":"EO1A1350972013086110KF, 2013-03-13, channels 973 (false color IR), Glaciers of Northwest Heard Island (mapped meanwhile)","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-S2A_R111_N09_20160604T154554","name":"imagico.de OSM images for mapping: Panama Canal","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R111_N09_20160604T154554&z={zoom}&x={x}&y={-y}","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)","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-LC81511242016033LGN00","name":"imagico.de OSM images for mapping: Pensacola Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81511242016033LGN00&z={zoom}&x={x}&y={-y}","description":"LC81511242016033LGN00/LC81511232016033LGN00, 2016-02-02, channels 234 (true color), Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox","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-S2A_R136_N41_20150831T093006","name":"imagico.de OSM images for mapping: Prokletije Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R136_N41_20150831T093006&z={zoom}&x={x}&y={-y}","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","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-DMS_1142622_03746_20110415_17533956","name":"imagico.de OSM images for mapping: Qasigiannguit","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=DMS_1142622_03746_20110415_17533956&z={zoom}&x={x}&y={-y}","description":"DMS_1142622_03746_20110415_17533956, 2011-04-15, true color, Icebridge DMS image of the settlement - alignment might be poor","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-LC81510432015030LGN00","name":"imagico.de OSM images for mapping: Rann of Kutch","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81510432015030LGN00&z={zoom}&x={x}&y={-y}","description":"various Landsat early 2015, channel 654 (false color IR), Land/water distinction difficult to properly map based on Bing/Mapbox images","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-S2A_R093_N41_20150828T092005","name":"imagico.de OSM images for mapping: Rila and Pirin Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R093_N41_20150828T092005&z={zoom}&x={x}&y={-y}","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","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-LC81730602015040LGN00","name":"imagico.de OSM images for mapping: Rwenzori Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81730602015040LGN00&z={zoom}&x={x}&y={-y}","description":"LC81730602015040LGN00, 2015-02-09, channel 654 (false color IR), Recent image of most of the remaining Rwenzori Mountains glaciers","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-LC80611072014036LGN00","name":"imagico.de OSM images for mapping: Scott Island","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80611072014036LGN00&z={zoom}&x={x}&y={-y}","description":"LC80611072014036LGN00, 2014-02-05, channels 234 (true color), Missing in other image sources","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-LC82100972015347LGN00","name":"imagico.de OSM images for mapping: Shag Rocks","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82100972015347LGN00&z={zoom}&x={x}&y={-y}","description":"LC82100972015347LGN00, 2015-12-13, channels 234 (true color), Missing in other image sources","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-LC81130622013270LGN00","name":"imagico.de OSM images for mapping: Southeastern Sulawesi","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81130622013270LGN00&z={zoom}&x={x}&y={-y}","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","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-LC80281222016035LGN00","name":"imagico.de OSM images for mapping: Southern Transantarctic Mountains","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80281222016035LGN00&z={zoom}&x={x}&y={-y}","description":"LC80281222016035LGN00/LC80281212016035LGN00, 2016-02-04, channels 234 (true color), Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox","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-DMS_1142636_160xx_20110507_1822xxxx","name":"imagico.de OSM images for mapping: Thule Air Base","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=DMS_1142636_160xx_20110507_1822xxxx&z={zoom}&x={x}&y={-y}","description":"DMS_1142636_16001_20110507_18221638-DMS_1142636_16076_20110507_18224996, 2011-05-07, true color, Icebridge DMS image - alignment might be poor","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-LC80910682014358LGN00","name":"imagico.de OSM images for mapping: Vanatinai","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80910682014358LGN00&z={zoom}&x={x}&y={-y}","description":"LC80910682014358LGN00, 2014-12-24, channels 234 (true color), Coarse coastline due to cloud cover in Bing/Mapbox","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-LC82330892016031LGN00","name":"imagico.de OSM images for mapping: Volcán Calbuco","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82330892016031LGN00&z={zoom}&x={x}&y={-y}","description":"LC82330892016031LGN00, 2016-01-31, channels 234 (true color), Image from after the 2015 eruption","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-LC81490352013282LGN00","name":"imagico.de OSM images for mapping: Western Karakoram","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81490352013282LGN00&z={zoom}&x={x}&y={-y}","description":"LC81490352013282LGN00, 2013-10-09, channels 234 (true color), Represents approximately minimum snow cover so can be well used for glacier mapping","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-S2A_R039_S15_20160510T145731","name":"imagico.de OSM images for mapping: Willkanuta Mountains and Quelccaya Ice Cap","type":"tms","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R039_S15_20160510T145731&z={zoom}&x={x}&y={-y}","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160511T025410_R039_V20160510T145731_20160510T150701, 2016-05-10, channels 234 (true color), Poor and outdated imagery in other sources","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":"Interspect_Budapest_2014","name":"Interspect ortofotó 2014","type":"tms","template":"http://geoserver.infobex.hu/Budapest2014/IST/{zoom}/{x}/{y}.jpg","description":"Four districts of Budapest: III, XIII, XIV, XV","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},{"id":"bartholomew_qi1940","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"},{"id":"GSGS3906","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":"GSGS4136","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":"IrelandEEACORINE2006","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"},{"id":"IrelandEEAGMESUrbanAtlas","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"},{"id":"gsi.go.jp","name":"Japan GSI ortho Imagery","type":"tms","template":"http://cyberjapandata.gsi.go.jp/xyz/ort/{zoom}/{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]]]},{"id":"Aargau-AGIS-2011","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"},{"id":"Aargau-AGIS-2014","name":"Kanton Aargau 25cm (AGIS 2014)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/AGIS2014/EPSG900913/{zoom}/{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},{"id":"KTBASELSTADT2015","name":"Kanton Basel-Stadt 2015","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/KTBASELSTADT2015/EPSG900913/{zoom}/{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"},{"id":"Solothurn-sogis2014-tms","name":"Kanton Solothurn 25cm (SOGIS 2014-2015)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/sogis2014/EPSG900913/{zoom}/{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},{"id":"KTZUERICH2015","name":"Kanton Zürich 2015  10cm","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/KTZUERICH2015/EPSG900913/{zoom}/{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},{"id":"kelowna_2012","name":"Kelowna 2012","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/kelowna2012/{zoom}/{x}/{y}.png","description":"High quality aerial imagery taken for the City of Kelowna","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","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]]],"overlay":true},{"id":"landsat_233055","name":"Landsat 233055","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/landsat_233055/{zoom}/{x}/{y}.png","description":"Recent Landsat imagery","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_047026","name":"Latest southwest British Columbia Landsat","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/landsat_047026/{zoom}/{x}/{y}.png","description":"Recent lower-resolution landsat imagery for southwest British Columbia","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":"ORT10LT","name":"Lithuania - NŽT ORT10LT","type":"tms","template":"http://mapproxy.openmap.lt/ort10lt/g/{zoom}/{x}/{y}.jpeg","scaleExtent":[1,18],"polygon":[[[26.2138385,55.850748],[26.3858298,55.7045315],[26.6303618,55.6806692],[26.6205349,55.5689227],[26.5242191,55.5099228],[26.5541476,55.388833],[26.4399286,55.3479351],[26.7919694,55.3212027],[26.8291304,55.2763488],[26.7434625,55.2539863],[26.6764846,55.158828],[26.4611191,55.1285624],[26.3577434,55.1505399],[26.2296342,55.1073177],[26.2713814,55.0775905],[26.2085126,54.997414],[26.0619117,54.9416094],[25.8578176,54.9276001],[25.7429827,54.8150641],[25.7626083,54.5769013],[25.5319352,54.3418175],[25.6771618,54.3238109],[25.7857293,54.2336242],[25.7858844,54.1550594],[25.5550843,54.1461918],[25.5109462,54.1750267],[25.5896725,54.2285838],[25.5136246,54.3078472],[25.2689287,54.2744706],[25.0705963,54.1336282],[24.9573726,54.1720575],[24.8133801,54.144862],[24.7790172,54.0999054],[24.8712786,54.034904],[24.819568,53.9977218],[24.6845912,53.9621091],[24.697865,54.0171421],[24.6259068,54.0105048],[24.4342619,53.9014424],[24.3520594,53.8967893],[24.2016059,53.9700069],[23.9683341,53.9266977],[23.9130177,53.9696842],[23.7781192,53.8989169],[23.7097655,53.9394502],[23.5370435,53.9430702],[23.4822428,53.9893848],[23.5273356,54.0473482],[23.4858579,54.1532339],[23.3867851,54.224838],[23.0421216,54.3159745],[23.0102115,54.3827959],[22.8546899,54.4104029],[22.7919963,54.3633227],[22.7023421,54.4528985],[22.6838586,54.585972],[22.7489713,54.6319792],[22.7429727,54.7268221],[22.8866837,54.8135001],[22.8204005,54.9119829],[22.6424041,54.9713362],[22.5892361,55.070243],[22.080597,55.0244812],[22.0324081,55.084098],[21.9130671,55.0816838],[21.6491949,55.1808113],[21.5015124,55.1868198],[21.3843708,55.2936996],[21.2709829,55.2450059],[21.0983616,55.2563884],[20.9421741,55.282453],[21.0863466,55.5618266],[21.0399547,55.8363584],[21.0640261,56.0699542],[21.2047804,56.0811668],[21.2307958,56.1623302],[21.5021038,56.2954952],[21.7235874,56.3138211],[21.8356623,56.37162],[21.9695397,56.3766515],[22.0153001,56.4242811],[22.4372717,56.406405],[22.6800028,56.3515884],[22.9191739,56.3790184],[22.9466759,56.4146477],[23.0932498,56.3046383],[23.1703443,56.3667721],[23.3064522,56.3830535],[23.5571715,56.3338187],[23.7647953,56.3733238],[23.7666897,56.3238079],[24.0189971,56.3297615],[24.1214631,56.2488984],[24.2857421,56.3006367],[24.4541496,56.2581579],[24.5794651,56.2882389],[24.6284061,56.3753322],[24.9023767,56.4805317],[25.1277405,56.2059091],[25.5771398,56.182414],[25.6731232,56.1493667],[26.2138385,55.850748]]],"terms_url":"http://www.geoportal.lt","terms_text":"NŽT ORT10LT"},{"id":"mapbox_locator_overlay","name":"Locator Overlay","type":"tms","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","description":"Shows major features to help orient you.","scaleExtent":[0,16],"overzoom":false,"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true,"overlay":true},{"id":"NSW_LPI_BaseMap","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_Imagery","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","best":true},{"id":"NSW_LPI_TopographicMap","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":"lu.geoportail.opendata.basemap","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.cadastre","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.ortho2010","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","best":true},{"id":"lu.geoportail.opendata.ortho2013","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","best":true},{"id":"lu.geoportail.opendata.topo","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":"Mapbox","name":"Mapbox Satellite","type":"tms","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","description":"Satellite and aerial imagery.","scaleExtent":[0,19],"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true},{"id":"geodata.md.gov-MD_SixInchImagery","name":"MD 2014 6 Inch Aerial Imagery","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/MD_SixInchImagery/http://geodata.md.gov/imap/services/Imagery/MD_SixInchImagery/MapServer/WmsServer","description":"Six Inch resolution aerial imagery for the State of Maryland","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"},{"id":"geodata.md.gov-MD_ColorBasemap","name":"MD Transportation Basemap","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/MD_ColorBasemap/http://geodata.md.gov/imap/services/Transportation/MD_ColorBasemap/MapServer/WmsServer","description":"Maryland State Highway Administration road features and additional Maryland focused landmarks","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"},{"id":"New_and_Misaligned_TIGER_Roads-2013","name":"New & Misaligned TIGER Roads","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/enf.e0b8291e/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJhNVlHd29ZIn0.ti6wATGDWOmCnCYen-Ip7Q","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","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},{"id":"geodata.state.nj.us-Infrared2015","name":"NJ 2015 Aerial Imagery (Infrared)","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/Infrared2015/http://geodata.state.nj.us/imagerywms/Infrared2015","description":"Digital orthophotography of New Jersey, Near Infrared, 1 foot resolution","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)"},{"id":"geodata.state.nj.us-Natural2015","name":"NJ 2015 Aerial Imagery (Natural Color)","type":"tms","template":"http://whoots.mapwarper.net/tms/{zoom}/{x}/{y}/Natural2015/http://geodata.state.nj.us/imagerywms/Natural2015","description":"Digital orthophotography of New Jersey, Natural Color, 1 foot resolution","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)"},{"id":"NLS-Bartholomew-hfinch-hist","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"},{"id":"NLS-OS-7th_Series","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"},{"id":"NLS-OS-1st_Series","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"},{"id":"NLS-OS-25inch-hist","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"},{"id":"NLS-OS-6inch-County-Series-hist","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"},{"id":"NLS-OS-6inch-Scotland-hist","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"},{"id":"MAPNIK","name":"OpenStreetMap (Standard)","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png","description":"The default OpenStreetMap layer.","scaleExtent":[0,19],"terms_url":"http://openstreetmap.org/","terms_text":"© OpenStreetMap contributors, CC-BY-SA","default":true},{"id":"osm-gps","name":"OpenStreetMap GPS traces","type":"tms","template":"http://{switch:a,b,c}.gps-tile.openstreetmap.org/lines/{zoom}/{x}/{y}.png","description":"Public GPS traces uploaded to OpenStreetMap.","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},{"id":"OS-historic-25k-OSM_Limited","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]]]},{"id":"OS-New_Popular_Edition-historic","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]]]},{"id":"OS-OpenData_Locator","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},{"id":"OS-OpenData_StreetView","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]]]},{"id":"OS-Scottish_Popular-historic","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]]]},{"id":"Pangasinan_Bulacan_HiRes","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]]]},{"id":"PNOA-Spain-TMS","name":"PNOA Spain","type":"tms","template":"http://www.ign.es/wmts/pnoa-ma?request=GetTile&service=WMTS&VERSION=1.0.0&Layer=OI.OrthoimageCoverage&Style=default&Format=image/png&TileMatrixSet=GoogleMapsCompatible&TileMatrix={zoom}&TileRow={y}&TileCol={x}","polygon":[[[-17.8846298,28.4460601],[-17.8939535,28.5225529],[-18.0212548,28.7481927],[-18.0224091,28.8038375],[-17.9424017,28.8726124],[-17.8911792,28.8737099],[-17.8903302,28.8515102],[-17.7675902,28.8537764],[-17.7669837,28.8312183],[-17.7412714,28.8319975],[-17.7394926,28.7642235],[-17.7139824,28.7649677],[-17.7129312,28.7303731],[-17.7574427,28.6931782],[-17.7570788,28.6741254],[-17.7457913,28.6743524],[-17.7457266,28.6165627],[-17.7519687,28.5833675],[-17.7622536,28.5591958],[-17.7833086,28.541667],[-17.7831575,28.4936643],[-17.808611,28.4925024],[-17.8060072,28.4468974],[-17.8846298,28.4460601]],[[-18.1661033,27.7851643],[-18.163494,27.6949247],[-18.0889827,27.6963366],[-18.0873398,27.6738724],[-18.0364092,27.6753701],[-18.0350079,27.6302571],[-17.9589987,27.6323976],[-17.8603269,27.7926025],[-17.8630328,27.8368793],[-17.8884015,27.8364947],[-17.8891263,27.8590536],[-17.9906491,27.8567467],[-18.0386803,27.7655831],[-18.1146412,27.7637873],[-18.1154627,27.7863613],[-18.1661033,27.7851643]],[[-17.36038,28.0639801],[-17.3629657,28.1757247],[-17.3375583,28.1763688],[-17.3384577,28.2213012],[-17.1857883,28.2238767],[-17.0820788,28.1351849],[-17.0808422,28.0679977],[-17.1315446,28.0668073],[-17.1563337,28.0214628],[-17.2321063,28.0203711],[-17.2319938,27.9980388],[-17.2576823,27.9978403],[-17.257851,28.0199741],[-17.3086658,28.0192298],[-17.36038,28.0639801]],[[-16.9278171,28.3275779],[-16.9286591,28.3721879],[-16.8776666,28.3729288],[-16.8780707,28.3954191],[-16.5214259,28.4226146],[-16.4457117,28.491135],[-16.4462506,28.535972],[-16.4205859,28.5362679],[-16.4209227,28.5588419],[-16.3443329,28.5597589],[-16.3446023,28.5822095],[-16.1912541,28.5837179],[-16.1916246,28.6068435],[-16.1279344,28.6078193],[-16.1277997,28.5921762],[-16.0995079,28.5925015],[-16.0993395,28.5163822],[-16.1648148,28.5161158],[-16.1647474,28.4938583],[-16.2385755,28.4484704],[-16.2653516,28.4476116],[-16.2658569,28.4030038],[-16.3167484,28.4017594],[-16.3163105,28.380189],[-16.3420763,28.3795075],[-16.3408301,28.2892963],[-16.415837,28.1976134],[-16.415096,28.1311312],[-16.5153297,28.0164796],[-16.6168433,28.01532],[-16.6168096,27.9930469],[-16.7184243,27.9919168],[-16.7190979,28.0371426],[-16.7446952,28.0367859],[-16.7453351,28.0818146],[-16.7706967,28.0816065],[-16.8223966,28.1259036],[-16.8231712,28.1708652],[-16.8487012,28.1707464],[-16.8502842,28.260791],[-16.8756457,28.2605537],[-16.8760836,28.2832162],[-16.9015125,28.2827713],[-16.9023882,28.3279337],[-16.9278171,28.3275779]],[[-15.8537427,27.9008901],[-15.8542032,27.9901812],[-15.828953,27.9906555],[-15.8291065,28.035578],[-15.7782992,28.0363232],[-15.7532793,28.0814298],[-15.7278756,28.0815652],[-15.7282593,28.1718567],[-15.4989741,28.1728039],[-15.4987438,28.1504075],[-15.4497785,28.1507459],[-15.4501622,28.1961425],[-15.3972827,28.1961425],[-15.3964385,28.0383554],[-15.3710348,28.0380167],[-15.3706511,28.0153212],[-15.3457847,28.0153212],[-15.3454777,27.9254406],[-15.3708046,27.9252372],[-15.3705743,27.8352137],[-15.395978,27.8347387],[-15.4209979,27.7879673],[-15.4718052,27.7893932],[-15.471882,27.7666454],[-15.522766,27.7667813],[-15.5477092,27.7216112],[-15.6236132,27.7213395],[-15.6241504,27.741991],[-15.7007451,27.7433495],[-15.801669,27.8110501],[-15.8537427,27.9008901]],[[-14.5215621,28.0467778],[-14.5224358,28.1184131],[-14.4157526,28.1156076],[-14.2168794,28.2278805],[-14.2153651,28.33903],[-14.1641672,28.4528287],[-14.1115132,28.4747955],[-14.0335806,28.7226671],[-13.9565217,28.7449351],[-13.9561722,28.7665857],[-13.8290221,28.7664325],[-13.8289639,28.7879765],[-13.8000741,28.7879255],[-13.8012972,28.7189894],[-13.827566,28.719347],[-13.8278572,28.6517968],[-13.8025786,28.651899],[-13.8033941,28.5384172],[-13.8288474,28.5384684],[-13.8315061,28.3970177],[-13.9158189,28.2241438],[-13.9856445,28.2235696],[-14.0369588,28.1795787],[-14.1387139,28.1799894],[-14.1386556,28.1579103],[-14.2153651,28.1578076],[-14.2147244,28.1118888],[-14.2913173,28.0452356],[-14.3319673,28.0368713],[-14.4457846,28.0469834],[-14.4466583,28.0657961],[-14.4962835,28.0682631],[-14.495934,28.0458525],[-14.5215621,28.0467778]],[[-13.800662,28.8456579],[-13.8009273,28.8231121],[-13.775688,28.8230539],[-13.69729,28.8898184],[-13.69729,28.9127744],[-13.6072498,28.9117991],[-13.4388551,29.0002417],[-13.4374559,29.1351289],[-13.4117005,29.1349931],[-13.4105556,29.2229789],[-13.4592801,29.255586],[-13.4597392,29.2942023],[-13.5091254,29.2945638],[-13.5100581,29.3163453],[-13.5635382,29.3172941],[-13.5640564,29.2713764],[-13.5389228,29.2711956],[-13.5389747,29.2500375],[-13.5661293,29.2501279],[-13.5665956,29.2030039],[-13.5156549,29.2022349],[-13.5156549,29.1820579],[-13.5398038,29.1827819],[-13.5408921,29.137528],[-13.65782,29.1368528],[-13.713222,29.0935079],[-13.7663353,29.0934533],[-13.8502463,29.0165937],[-13.8518224,28.983425],[-13.8524443,28.914861],[-13.9013122,28.89245],[-13.9024005,28.8469779],[-13.800662,28.8456579]],[[1.6479916,38.9990693],[1.7321668,38.9993635],[1.7314703,39.0441733],[1.6489512,39.0431944],[1.6481552,39.1276358],[1.3948608,39.1265691],[1.3954412,39.0864199],[1.2281145,39.0852615],[1.2291095,39.0028958],[1.1448657,39.0018003],[1.1452803,38.8319988],[1.3113632,38.8331615],[1.3121924,38.7906483],[1.3946949,38.7916178],[1.3951924,38.7529597],[1.3112803,38.7519251],[1.3125919,38.6238804],[1.6489036,38.6251112],[1.6480745,38.7111504],[1.58456,38.7101152],[1.5811604,38.7005387],[1.5491544,38.7002798],[1.5197188,38.7092094],[1.50355,38.7253185],[1.4813282,38.9155064],[1.5518906,38.9254411],[1.5667328,38.9566554],[1.6487378,38.9583318],[1.6479916,38.9990693]],[[2.5450749,39.4166673],[2.43933,39.4161122],[2.438714,39.4846853],[2.439022,39.4993424],[2.3122308,39.4993424],[2.3119228,39.5417911],[2.2290722,39.5409994],[2.2283536,39.6260571],[2.3460076,39.6270851],[2.9270445,39.9601558],[3.1456647,39.9600498],[3.1460753,40.0019797],[3.2313899,40.0019797],[3.2312872,39.8329231],[3.1482313,39.8331596],[3.1484366,39.7935717],[3.4814817,39.7931773],[3.4803472,39.5959027],[3.3150618,39.4784606],[3.3146179,39.3785504],[3.0830178,39.2499355],[2.9798608,39.2501482],[2.9790395,39.3334971],[2.7287424,39.3334177],[2.7288451,39.4581361],[2.6456865,39.4577397],[2.6453785,39.4996593],[2.5452802,39.4994216],[2.5450749,39.4166673]],[[3.8120402,40.0434431],[3.729082,40.0437979],[3.7286185,39.9584155],[3.8126633,39.9576011],[3.8122771,39.9164393],[3.9608975,39.9159813],[4.1938142,39.791308],[4.3150279,39.7905799],[4.3159934,39.8329294],[4.3987393,39.8320396],[4.3973664,39.9185834],[4.3158003,39.9193274],[4.3161865,40.0433985],[4.2318959,40.0443594],[4.2324752,40.0847793],[4.1491501,40.086109],[4.1490623,40.1255157],[4.0627981,40.1272166],[4.0624217,40.0849941],[3.8128687,40.085294],[3.8120402,40.0434431]],[[-8.8910646,41.8228891],[-9.1092038,42.5751065],[-9.0365469,42.730656],[-9.0883419,42.7269569],[-9.1466113,42.7750272],[-9.2185488,42.9016271],[-9.2760988,42.8605106],[-9.3099094,42.9311297],[-9.2789763,42.9821991],[-9.3099094,43.0600377],[-9.2523594,43.1041725],[-9.2314975,43.1703151],[-9.1473307,43.210176],[-9.06748,43.1991644],[-9.0336694,43.2426748],[-8.99842,43.2447709],[-8.9998588,43.2955793],[-8.9372732,43.3055265],[-8.92936,43.326986],[-8.8638969,43.3290792],[-8.8761263,43.3740655],[-8.8221732,43.3735426],[-8.785485,43.3191358],[-8.7063538,43.305003],[-8.6099575,43.3296025],[-8.5509688,43.3233227],[-8.5243519,43.3364048],[-8.5250713,43.3646525],[-8.45745,43.3918416],[-8.3610538,43.4111803],[-8.3603344,43.4634161],[-8.3344369,43.5797394],[-8.2776063,43.5708796],[-8.0646713,43.7239184],[-7.9992081,43.7233986],[-7.9171994,43.7826357],[-7.8560525,43.7914643],[-7.83591,43.7374337],[-7.6628443,43.809819],[-7.3188932,43.6782695],[-7.1997467,43.5830817],[-6.2488228,43.6075032],[-6.1229322,43.5790105],[-5.8520425,43.6798953],[-5.6036334,43.5708672],[-5.2855347,43.5619084],[-5.1787525,43.4991591],[-4.9089869,43.4836655],[-4.6156167,43.4192021],[-4.1839917,43.4249168],[-3.8029478,43.5195394],[-3.7400025,43.4869277],[-3.5612827,43.5423572],[-3.1083013,43.3816347],[-2.9385737,43.4624573],[-2.7452417,43.4755094],[-2.3046245,43.3170625],[-1.9854018,43.3563045],[-1.8552841,43.3972545],[-1.769802,43.3964383],[-1.7700492,43.3760501],[-1.7100474,43.3756908],[-1.7113451,43.3312527],[-1.7225915,43.3131806],[-1.6890375,43.3129108],[-1.6881106,43.3341294],[-1.6446695,43.3337248],[-1.6449785,43.3133155],[-1.6029903,43.3129528],[-1.6034352,43.2926624],[-1.5635905,43.2921227],[-1.5630468,43.3133844],[-1.4779905,43.3128355],[-1.3667723,43.2761368],[-1.3568809,43.2381533],[-1.3703692,43.1712972],[-1.4423067,43.0833554],[-1.4198262,43.0603647],[-1.3730668,43.051166],[-1.3640746,43.1115893],[-1.3020285,43.135217],[-1.2354864,43.1332484],[-1.2795481,43.0774443],[-1.1923239,43.0649635],[-1.0061856,43.0077821],[-0.942341,42.9748951],[-0.7562028,42.9821318],[-0.7148387,42.9610774],[-0.6968543,42.9031405],[-0.5511809,42.8220693],[-0.5044215,42.8484456],[-0.4288871,42.8200906],[-0.3164848,42.8655842],[-0.1456332,42.810856],[-0.0314324,42.7124874],[0.1861785,42.7540985],[0.3021777,42.7177729],[0.3642238,42.7428729],[0.4487504,42.7144695],[0.6276949,42.7223973],[0.6411832,42.8576747],[0.7149192,42.882718],[0.9675996,42.8181119],[1.108777,42.7989808],[1.1753192,42.7342872],[1.3632559,42.7415521],[1.4113736,42.7093914],[1.4806054,42.7103407],[1.4813006,42.5010664],[1.6443591,42.5020345],[1.6432777,42.5424539],[1.730407,42.5434214],[1.7316429,42.5011803],[2.0638621,42.5016359],[2.0645572,42.4590247],[2.3969309,42.4599364],[2.3976786,42.4178363],[2.4804823,42.4179732],[2.4809767,42.3759441],[2.6447922,42.3762636],[2.6444832,42.4592447],[2.8113266,42.4596094],[2.8112648,42.5010358],[3.063878,42.5008535],[3.063878,42.4591535],[3.2307832,42.4593359],[3.2304935,42.3764363],[3.3141469,42.3760369],[3.3141243,42.3339864],[3.397855,42.3340435],[3.3973912,42.290094],[3.3138923,42.2908368],[3.3139695,42.2070151],[3.1475896,42.2073012],[3.1475896,42.1260612],[3.2305478,42.1260039],[3.2466753,41.9529359],[3.1945206,41.8558943],[3.060537,41.7647419],[2.7835777,41.6371796],[2.26293,41.4271601],[2.1649151,41.2989297],[1.86008,41.2232228],[1.3763003,41.116273],[1.1793714,41.0464585],[1.0858526,41.048493],[0.758537,40.8195599],[0.9114042,40.733761],[0.8781331,40.6751363],[0.6650182,40.5358666],[0.5580112,40.5502166],[0.433919,40.3757589],[0.2675635,40.1919192],[0.1641534,40.0647234],[0.0751307,40.0144671],[0.010387,39.8952188],[-0.0939224,39.8116904],[-0.1847435,39.6311716],[-0.2908513,39.5036254],[-0.2863552,39.333431],[-0.1856427,39.1774612],[-0.2135185,39.1558487],[-0.1110076,38.9722246],[0.0094878,38.8826835],[0.1218901,38.872183],[0.2342925,38.798636],[0.2558737,38.7264162],[0.0958128,38.6133825],[-0.0022021,38.6070586],[-0.0570544,38.5269073],[-0.2719677,38.4762395],[-0.379874,38.3931234],[-0.3834708,38.3381297],[-0.4509122,38.3310763],[-0.5048654,38.2830943],[-0.4823849,38.1948095],[-0.429331,38.1658287],[-0.4545091,38.148859],[-0.5839966,38.1721913],[-0.6136708,38.1198599],[-0.6370505,37.9612228],[-0.6811123,37.9456238],[-0.7323677,37.8810656],[-0.7215771,37.7830562],[-0.688306,37.7340026],[-0.6641461,37.6231485],[-0.7193941,37.5878413],[-0.9196258,37.5375806],[-1.1107098,37.5164093],[-1.3383246,37.5286671],[-1.4408917,37.3903714],[-1.6766966,37.2765189],[-1.8540816,36.9122889],[-2.0683486,36.6929117],[-2.2158766,36.6619233],[-2.3721861,36.7801753],[-2.6812926,36.6591056],[-2.9201476,36.6675585],[-3.09402,36.712625],[-3.4610839,36.6548788],[-3.7280395,36.6929117],[-4.3743529,36.6633322],[-4.6571151,36.4404171],[-4.9188018,36.4531321],[-5.1699508,36.3513541],[-5.2841094,36.1970201],[-5.2680911,36.1241812],[-5.3524784,36.1224654],[-5.3516094,36.0401413],[-5.4365759,36.0388921],[-5.4353207,36.0034384],[-5.6888562,36.0036518],[-5.6899635,36.0405317],[-5.85506,36.0385595],[-5.8566821,36.1242077],[-5.9384817,36.1221487],[-5.9400265,36.1655625],[-5.9983445,36.1645024],[-6.0357297,36.1780957],[-6.0775178,36.2224132],[-6.1506113,36.2864561],[-6.231541,36.3770075],[-6.3358504,36.5310643],[-6.3214629,36.5816265],[-6.404191,36.6234958],[-6.4743301,36.7489673],[-6.4158808,36.7993866],[-6.490516,36.9173818],[-6.6298949,37.0194012],[-6.8744824,37.1083766],[-7.0426363,37.1850699],[-7.2647434,37.1843535],[-7.3753473,37.1535419],[-7.408316,37.1682196],[-7.4202886,37.2118318],[-7.4249231,37.2350505],[-7.4380543,37.2451969],[-7.4459717,37.3326142],[-7.4480958,37.3909382],[-7.4696271,37.4075829],[-7.4647029,37.4530494],[-7.5019723,37.516411],[-7.5191587,37.5229203],[-7.5219588,37.5723727],[-7.4501271,37.6695835],[-7.4249019,37.7599222],[-7.316662,37.839974],[-7.268329,37.988952],[-7.1536786,38.0155235],[-7.1177098,38.0553626],[-7.0142997,38.0243785],[-6.9963153,38.1075633],[-6.9614706,38.201254],[-7.080617,38.1570753],[-7.3402665,38.4402363],[-7.2638329,38.7380741],[-7.0435243,38.8729667],[-7.0615086,38.907962],[-6.9693387,39.0198308],[-7.0008114,39.0887867],[-7.1536786,39.0957658],[-7.1525545,39.1602899],[-7.2447245,39.1968854],[-7.2559647,39.2813308],[-7.3368944,39.3535074],[-7.3279022,39.4559917],[-7.5144901,39.5886496],[-7.5527069,39.6795427],[-7.0502684,39.6752171],[-6.9951913,39.8195433],[-6.9221297,39.8790868],[-6.886161,40.0229854],[-7.0412762,40.1347927],[-7.0176717,40.266146],[-6.8086034,40.3450071],[-6.8681766,40.4451649],[-6.8535643,40.6066433],[-6.837828,40.8757589],[-6.9536024,41.0370445],[-6.8018592,41.0395879],[-6.7681385,41.138706],[-6.6411239,41.2655616],[-6.5624422,41.2630269],[-6.217367,41.5791017],[-6.3162811,41.644652],[-6.5152332,41.6412921],[-6.5871707,41.6883151],[-6.5478299,41.8559743],[-6.6298836,41.9112057],[-7.1334461,41.9404756],[-7.1682909,41.8718791],[-7.4256922,41.7847727],[-7.9539833,41.8459271],[-8.130455,41.7805819],[-8.2518495,41.9078597],[-8.1293309,42.0348842],[-8.2484774,42.1008034],[-8.3676239,42.0557521],[-8.6070409,42.0340493],[-8.8910646,41.8228891]]],"terms_text":"PNOA"},{"id":"Slovakia-Historic-Maps","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]]]},{"id":"South_Africa-CD_NGI-Aerial","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},{"id":"South-Tyrol-Orthofoto2011","name":"South Tyrol Orthofoto 2011","type":"tms","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","description":"Orthophoto of South Tyrol from 2011","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-Orthofoto2014","name":"South Tyrol Orthofoto 2014","type":"tms","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","description":"Orthophoto of South Tyrol from 2011","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","best":true},{"id":"South-Tyrol-Topomap","name":"South Tyrol Topomap","type":"tms","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{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","description":"Topographical basemap of South Tyrol","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":"Bern-bern2016-tms","name":"Stadt Bern 10cm (2016)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/bern2016/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[8,21],"polygon":[[[7.2943145,46.9237564],[7.2982665,46.9274715],[7.3061586,46.9309487],[7.3043338,46.9362344],[7.3068603,46.9403709],[7.3246431,46.9432765],[7.3284525,46.946409],[7.3414051,46.9460797],[7.3438454,46.9473713],[7.3434554,46.9487937],[7.3513567,46.9485481],[7.3505628,46.950213],[7.3530901,46.9519266],[7.3582028,46.9511773],[7.3685031,46.9566244],[7.3715097,46.9607339],[7.37503,46.959835],[7.3785111,46.9614686],[7.3806232,46.9654741],[7.3832097,46.9663014],[7.3937998,46.9669268],[7.4000528,46.9691779],[7.4082922,46.9686857],[7.4281713,46.9738041],[7.4327053,46.972689],[7.4353602,46.9684345],[7.4378522,46.9684302],[7.4412474,46.9767865],[7.4456893,46.9747939],[7.4483835,46.9756393],[7.4477006,46.9790125],[7.4440468,46.9780682],[7.4412738,46.9798224],[7.4506732,46.9901527],[7.4522112,46.9896803],[7.454649,46.9778182],[7.4680382,46.9758258],[7.4707923,46.969998],[7.4701907,46.9674116],[7.4781618,46.9711823],[7.4845237,46.9701571],[7.4861275,46.9679018],[7.4857945,46.9646828],[7.4784708,46.9629043],[7.4802865,46.9606768],[7.4789304,46.9587841],[7.4797786,46.9566019],[7.4770135,46.9544586],[7.4840504,46.9499938],[7.4833925,46.9451977],[7.4955563,46.9396169],[7.4935119,46.9376594],[7.4908036,46.9387617],[7.4894997,46.9368667],[7.4766667,46.9369496],[7.4781093,46.9362489],[7.4746986,46.9339187],[7.4753537,46.9329898],[7.4691047,46.9292427],[7.4707683,46.9255044],[7.4585674,46.934836],[7.4476373,46.9304297],[7.435418,46.9349668],[7.4338022,46.9331237],[7.4376403,46.9307415],[7.4146941,46.9368183],[7.413844,46.9315682],[7.4070798,46.9303824],[7.408065,46.9256296],[7.4021268,46.9241992],[7.4014835,46.9211927],[7.3875736,46.9304506],[7.3823129,46.927282],[7.3800187,46.9298929],[7.3808694,46.9324085],[7.3748669,46.9314306],[7.3748901,46.9327104],[7.368066,46.9323929],[7.3683058,46.930426],[7.3604074,46.9285884],[7.3605592,46.9272018],[7.338783,46.9245357],[7.3393683,46.9196675],[7.3274574,46.9190326],[7.3269178,46.9235974],[7.324374,46.9251891],[7.3082264,46.9222857],[7.2943145,46.9237564]]],"terms_text":"Orthophoto 2016, Vermessungsamt Stadt Bern ","best":true},{"id":"Uster-2008","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"},{"id":"Zuerich-zh_luftbild2011-tms","name":"Stadt Zürich Luftbild 2011","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_luftbild2011/EPSG900913/{zoom}/{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"},{"id":"Zuerich-city_map","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"},{"id":"stamen-terrain-background","name":"Stamen Terrain","type":"tms","template":"http://{switch:a,b,c,d}.tile.stamen.com/terrain-background/{zoom}/{x}/{y}.jpg","scaleExtent":[4,18],"terms_url":"http://maps.stamen.com/#terrain","terms_text":"Map tiles by Stamen Design, under CC BY 3.0"},{"id":"Stevns_Denmark","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"},{"id":"Surrey-Air_Survey","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]]]},{"id":"Szeged_2011","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"},{"id":"tnris.org","name":"Texas Orthophoto","type":"tms","template":"https://txgi.tnris.org/login/path/ecology-fiona-poem-romeo/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=texas&STYLE=&FORMAT=image/png&tileMatrixSet=0to20&tileMatrix=0to20:{zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,20],"polygon":[[[-99.9985439,34.5601834],[-95.55654502453,33.99257450647],[-93.89679027134,33.61039304449],[-93.98468089634,32.04103124103],[-93.41613841587,31.02505269211],[-93.74531484297,29.57268254375],[-96.50492070332,28.23158511753],[-97.36942054453,26.95467452634],[-97.04866958924,25.80530249434],[-99.0734177889,26.32559221139],[-100.76599193149,29.02531904433],[-102.3315436893,29.8433892263],[-103.13354564242,28.88112103669],[-104.2887874222,29.28831477845],[-104.7269783935,29.94815782859],[-104.72696778796,30.23535241761],[-106.53450082091,31.78456647831],[-106.75767043939,31.78457253947],[-106.75766067978,32.04385536686],[-106.61848436611,32.04385159755],[-103.11949492759,32.04375683439],[-103.09544343487,36.50045758762],[-103.05798056071,36.54268645422],[-100.00042146824,36.54222227302],[-99.9985439,34.5601834]]],"terms_url":"https://tnris.org/maps-and-data/online-mapping-services/"},{"id":"tf-landscape","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"},{"id":"Toulouse-Orthophotoplan-2007","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"},{"id":"Toulouse-Orthophotoplan-2011","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"},{"id":"Toulouse-Orthophotoplan-2013","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"},{"id":"Toulouse-Orthophotoplan-2015","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"},{"id":"Tours-Orthophoto-2008_2010","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"},{"id":"Tours-Orthophoto-2013","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"},{"id":"US_Forest_Service_roads","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]]]},{"id":"Zuerich-zh_uebersichtsplan-tms","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"},{"id":"USGS-Large_Scale","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]]]},{"id":"USGS-Scanned_Topographic","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]]]},{"id":"sjcgis.org-General_Basemap_WM","name":"Vector Streetmap for San Juan County WA","type":"tms","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/General_Basemap_WM/MapServer/tile/{zoom}/{y}/{x}","description":"Public domain street and address data from the San Juan County, WA. Updated at least quarterly.","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},{"id":"Vejmidte_Denmark","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"},{"id":"wien.gv.at-labels","name":"Vienna: Beschriftungen (annotations)","type":"tms","template":"https://maps.wien.gv.at/wmts/beschriftung/normal/google3857/{zoom}/{y}/{x}.png","scaleExtent":[12,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"https://data.wien.gv.at/","terms_text":"Stadt Wien"},{"id":"wien.gv.at-gp","name":"Vienna: Mehrzweckkarte (general purpose)","type":"tms","template":"https://maps.wien.gv.at/wmts/fmzk/pastell/google3857/{zoom}/{y}/{x}.jpeg","scaleExtent":[10,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"https://data.wien.gv.at/","terms_text":"Stadt Wien"},{"id":"wien.gv.at-aerial_image","name":"Vienna: Orthofoto (aerial image)","type":"tms","template":"https://maps.wien.gv.at/wmts/lb/farbe/google3857/{zoom}/{y}/{x}.jpeg","scaleExtent":[10,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"https://data.wien.gv.at/","terms_text":"Stadt Wien"}];
18961
18962 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}};
18963
18964 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"]};
18965
18966 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"]}};
18967
18968 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"}};
18969
18970 var data = {
18971     imagery: dataImagery,
18972     presets: {
18973         presets: presets,
18974         defaults: defaults,
18975         categories: categories,
18976         fields: fields
18977     }
18978 };
18979
18980 function osmEntity$$1(attrs) {
18981     // For prototypal inheritance.
18982     if (this instanceof osmEntity$$1) return;
18983
18984     // Create the appropriate subtype.
18985     if (attrs && attrs.type) {
18986         return osmEntity$$1[attrs.type].apply(this, arguments);
18987     } else if (attrs && attrs.id) {
18988         return osmEntity$$1[osmEntity$$1.id.type(attrs.id)].apply(this, arguments);
18989     }
18990
18991     // Initialize a generic Entity (used only in tests).
18992     return (new osmEntity$$1()).initialize(arguments);
18993 }
18994
18995
18996 osmEntity$$1.id = function(type) {
18997     return osmEntity$$1.id.fromOSM(type, osmEntity$$1.id.next[type]--);
18998 };
18999
19000
19001 osmEntity$$1.id.next = {
19002     node: -1, way: -1, relation: -1
19003 };
19004
19005
19006 osmEntity$$1.id.fromOSM = function(type, id) {
19007     return type[0] + id;
19008 };
19009
19010
19011 osmEntity$$1.id.toOSM = function(id) {
19012     return id.slice(1);
19013 };
19014
19015
19016 osmEntity$$1.id.type = function(id) {
19017     return { 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
19018 };
19019
19020
19021 // A function suitable for use as the second argument to d3.selection#data().
19022 osmEntity$$1.key = function(entity) {
19023     return entity.id + 'v' + (entity.v || 0);
19024 };
19025
19026
19027 osmEntity$$1.prototype = {
19028
19029     tags: {},
19030
19031
19032     initialize: function(sources) {
19033         for (var i = 0; i < sources.length; ++i) {
19034             var source = sources[i];
19035             for (var prop in source) {
19036                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
19037                     if (source[prop] === undefined) {
19038                         delete this[prop];
19039                     } else {
19040                         this[prop] = source[prop];
19041                     }
19042                 }
19043             }
19044         }
19045
19046         if (!this.id && this.type) {
19047             this.id = osmEntity$$1.id(this.type);
19048         }
19049         if (!this.hasOwnProperty('visible')) {
19050             this.visible = true;
19051         }
19052
19053         if (debug) {
19054             Object.freeze(this);
19055             Object.freeze(this.tags);
19056
19057             if (this.loc) Object.freeze(this.loc);
19058             if (this.nodes) Object.freeze(this.nodes);
19059             if (this.members) Object.freeze(this.members);
19060         }
19061
19062         return this;
19063     },
19064
19065
19066     copy: function(resolver, copies) {
19067         if (copies[this.id])
19068             return copies[this.id];
19069
19070         var copy = osmEntity$$1(this, {id: undefined, user: undefined, version: undefined});
19071         copies[this.id] = copy;
19072
19073         return copy;
19074     },
19075
19076
19077     osmId: function() {
19078         return osmEntity$$1.id.toOSM(this.id);
19079     },
19080
19081
19082     isNew: function() {
19083         return this.osmId() < 0;
19084     },
19085
19086
19087     update: function(attrs) {
19088         return osmEntity$$1(this, attrs, {v: 1 + (this.v || 0)});
19089     },
19090
19091
19092     mergeTags: function(tags) {
19093         var merged = lodash.clone(this.tags), changed = false;
19094         for (var k in tags) {
19095             var t1 = merged[k],
19096                 t2 = tags[k];
19097             if (!t1) {
19098                 changed = true;
19099                 merged[k] = t2;
19100             } else if (t1 !== t2) {
19101                 changed = true;
19102                 merged[k] = lodash.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
19103             }
19104         }
19105         return changed ? this.update({tags: merged}) : this;
19106     },
19107
19108
19109     intersects: function(extent, resolver) {
19110         return this.extent(resolver).intersects(extent);
19111     },
19112
19113
19114     isUsed: function(resolver) {
19115         return lodash.without(Object.keys(this.tags), 'area').length > 0 ||
19116             resolver.parentRelations(this).length > 0;
19117     },
19118
19119
19120     hasInterestingTags: function() {
19121         return lodash.keys(this.tags).some(osmIsInterestingTag);
19122     },
19123
19124
19125     isHighwayIntersection: function() {
19126         return false;
19127     },
19128
19129
19130     deprecatedTags: function() {
19131         var tags = lodash.toPairs(this.tags);
19132         var deprecated = {};
19133
19134         dataDeprecated.forEach(function(d) {
19135             var match = lodash.toPairs(d.old)[0];
19136             tags.forEach(function(t) {
19137                 if (t[0] === match[0] &&
19138                     (t[1] === match[1] || match[1] === '*')) {
19139                     deprecated[t[0]] = t[1];
19140                 }
19141             });
19142         });
19143
19144         return deprecated;
19145     }
19146 };
19147
19148 function geoExtent$$1(min, max) {
19149     if (!(this instanceof geoExtent$$1)) return new geoExtent$$1(min, max);
19150     if (min instanceof geoExtent$$1) {
19151         return min;
19152     } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
19153         this[0] = min[0];
19154         this[1] = min[1];
19155     } else {
19156         this[0] = min        || [ Infinity,  Infinity];
19157         this[1] = max || min || [-Infinity, -Infinity];
19158     }
19159 }
19160
19161 geoExtent$$1.prototype = new Array(2);
19162
19163 lodash.extend(geoExtent$$1.prototype, {
19164
19165     equals: function (obj) {
19166         return this[0][0] === obj[0][0] &&
19167             this[0][1] === obj[0][1] &&
19168             this[1][0] === obj[1][0] &&
19169             this[1][1] === obj[1][1];
19170     },
19171
19172
19173     extend: function(obj) {
19174         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19175         return geoExtent$$1(
19176             [Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
19177             [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
19178         );
19179     },
19180
19181
19182     _extend: function(extent) {
19183         this[0][0] = Math.min(extent[0][0], this[0][0]);
19184         this[0][1] = Math.min(extent[0][1], this[0][1]);
19185         this[1][0] = Math.max(extent[1][0], this[1][0]);
19186         this[1][1] = Math.max(extent[1][1], this[1][1]);
19187     },
19188
19189
19190     area: function() {
19191         return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
19192     },
19193
19194
19195     center: function() {
19196         return [(this[0][0] + this[1][0]) / 2,
19197                 (this[0][1] + this[1][1]) / 2];
19198     },
19199
19200
19201     rectangle: function() {
19202         return [this[0][0], this[0][1], this[1][0], this[1][1]];
19203     },
19204
19205
19206     bbox: function() {
19207         return { minX: this[0][0], minY: this[0][1], maxX: this[1][0], maxY: this[1][1] };
19208     },
19209
19210
19211     polygon: function() {
19212         return [
19213             [this[0][0], this[0][1]],
19214             [this[0][0], this[1][1]],
19215             [this[1][0], this[1][1]],
19216             [this[1][0], this[0][1]],
19217             [this[0][0], this[0][1]]
19218         ];
19219     },
19220
19221
19222     contains: function(obj) {
19223         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19224         return obj[0][0] >= this[0][0] &&
19225                obj[0][1] >= this[0][1] &&
19226                obj[1][0] <= this[1][0] &&
19227                obj[1][1] <= this[1][1];
19228     },
19229
19230
19231     intersects: function(obj) {
19232         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19233         return obj[0][0] <= this[1][0] &&
19234                obj[0][1] <= this[1][1] &&
19235                obj[1][0] >= this[0][0] &&
19236                obj[1][1] >= this[0][1];
19237     },
19238
19239
19240     intersection: function(obj) {
19241         if (!this.intersects(obj)) return new geoExtent$$1();
19242         return new geoExtent$$1(
19243             [Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
19244             [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
19245         );
19246     },
19247
19248
19249     percentContainedIn: function(obj) {
19250         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19251         var a1 = this.intersection(obj).area(),
19252             a2 = this.area();
19253
19254         if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
19255             return 0;
19256         } else {
19257             return a1 / a2;
19258         }
19259     },
19260
19261
19262     padByMeters: function(meters) {
19263         var dLat = geoMetersToLat(meters),
19264             dLon = geoMetersToLon(meters, this.center()[1]);
19265         return geoExtent$$1(
19266             [this[0][0] - dLon, this[0][1] - dLat],
19267             [this[1][0] + dLon, this[1][1] + dLat]
19268         );
19269     },
19270
19271
19272     toParam: function() {
19273         return this.rectangle().join(',');
19274     }
19275
19276 });
19277
19278 var version = "4.3.0";
19279
19280 var ascending = function(a, b) {
19281   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
19282 };
19283
19284 var bisector = function(compare) {
19285   if (compare.length === 1) compare = ascendingComparator(compare);
19286   return {
19287     left: function(a, x, lo, hi) {
19288       if (lo == null) lo = 0;
19289       if (hi == null) hi = a.length;
19290       while (lo < hi) {
19291         var mid = lo + hi >>> 1;
19292         if (compare(a[mid], x) < 0) lo = mid + 1;
19293         else hi = mid;
19294       }
19295       return lo;
19296     },
19297     right: function(a, x, lo, hi) {
19298       if (lo == null) lo = 0;
19299       if (hi == null) hi = a.length;
19300       while (lo < hi) {
19301         var mid = lo + hi >>> 1;
19302         if (compare(a[mid], x) > 0) hi = mid;
19303         else lo = mid + 1;
19304       }
19305       return lo;
19306     }
19307   };
19308 };
19309
19310 function ascendingComparator(f) {
19311   return function(d, x) {
19312     return ascending(f(d), x);
19313   };
19314 }
19315
19316 var ascendingBisect = bisector(ascending);
19317 var bisectRight = ascendingBisect.right;
19318 var bisectLeft = ascendingBisect.left;
19319
19320 var descending = function(a, b) {
19321   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
19322 };
19323
19324 var number = function(x) {
19325   return x === null ? NaN : +x;
19326 };
19327
19328 var variance = function(array, f) {
19329   var n = array.length,
19330       m = 0,
19331       a,
19332       d,
19333       s = 0,
19334       i = -1,
19335       j = 0;
19336
19337   if (f == null) {
19338     while (++i < n) {
19339       if (!isNaN(a = number(array[i]))) {
19340         d = a - m;
19341         m += d / ++j;
19342         s += d * (a - m);
19343       }
19344     }
19345   }
19346
19347   else {
19348     while (++i < n) {
19349       if (!isNaN(a = number(f(array[i], i, array)))) {
19350         d = a - m;
19351         m += d / ++j;
19352         s += d * (a - m);
19353       }
19354     }
19355   }
19356
19357   if (j > 1) return s / (j - 1);
19358 };
19359
19360 var deviation = function(array, f) {
19361   var v = variance(array, f);
19362   return v ? Math.sqrt(v) : v;
19363 };
19364
19365 var extent = function(array, f) {
19366   var i = -1,
19367       n = array.length,
19368       a,
19369       b,
19370       c;
19371
19372   if (f == null) {
19373     while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; }
19374     while (++i < n) if ((b = array[i]) != null) {
19375       if (a > b) a = b;
19376       if (c < b) c = b;
19377     }
19378   }
19379
19380   else {
19381     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = c = b; break; }
19382     while (++i < n) if ((b = f(array[i], i, array)) != null) {
19383       if (a > b) a = b;
19384       if (c < b) c = b;
19385     }
19386   }
19387
19388   return [a, c];
19389 };
19390
19391 var array = Array.prototype;
19392
19393 var slice = array.slice;
19394 var map = array.map;
19395
19396 var constant$1 = function(x) {
19397   return function() {
19398     return x;
19399   };
19400 };
19401
19402 var identity = function(x) {
19403   return x;
19404 };
19405
19406 var range = function(start, stop, step) {
19407   start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
19408
19409   var i = -1,
19410       n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
19411       range = new Array(n);
19412
19413   while (++i < n) {
19414     range[i] = start + i * step;
19415   }
19416
19417   return range;
19418 };
19419
19420 var e10 = Math.sqrt(50);
19421 var e5 = Math.sqrt(10);
19422 var e2 = Math.sqrt(2);
19423
19424 var ticks = function(start, stop, count) {
19425   var step = tickStep(start, stop, count);
19426   return range(
19427     Math.ceil(start / step) * step,
19428     Math.floor(stop / step) * step + step / 2, // inclusive
19429     step
19430   );
19431 };
19432
19433 function tickStep(start, stop, count) {
19434   var step0 = Math.abs(stop - start) / Math.max(0, count),
19435       step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
19436       error = step0 / step1;
19437   if (error >= e10) step1 *= 10;
19438   else if (error >= e5) step1 *= 5;
19439   else if (error >= e2) step1 *= 2;
19440   return stop < start ? -step1 : step1;
19441 }
19442
19443 var sturges = function(values) {
19444   return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
19445 };
19446
19447 var histogram = function() {
19448   var value = identity,
19449       domain = extent,
19450       threshold = sturges;
19451
19452   function histogram(data) {
19453     var i,
19454         n = data.length,
19455         x,
19456         values = new Array(n);
19457
19458     for (i = 0; i < n; ++i) {
19459       values[i] = value(data[i], i, data);
19460     }
19461
19462     var xz = domain(values),
19463         x0 = xz[0],
19464         x1 = xz[1],
19465         tz = threshold(values, x0, x1);
19466
19467     // Convert number of thresholds into uniform thresholds.
19468     if (!Array.isArray(tz)) tz = ticks(x0, x1, tz);
19469
19470     // Remove any thresholds outside the domain.
19471     var m = tz.length;
19472     while (tz[0] <= x0) tz.shift(), --m;
19473     while (tz[m - 1] >= x1) tz.pop(), --m;
19474
19475     var bins = new Array(m + 1),
19476         bin;
19477
19478     // Initialize bins.
19479     for (i = 0; i <= m; ++i) {
19480       bin = bins[i] = [];
19481       bin.x0 = i > 0 ? tz[i - 1] : x0;
19482       bin.x1 = i < m ? tz[i] : x1;
19483     }
19484
19485     // Assign data to bins by value, ignoring any outside the domain.
19486     for (i = 0; i < n; ++i) {
19487       x = values[i];
19488       if (x0 <= x && x <= x1) {
19489         bins[bisectRight(tz, x, 0, m)].push(data[i]);
19490       }
19491     }
19492
19493     return bins;
19494   }
19495
19496   histogram.value = function(_) {
19497     return arguments.length ? (value = typeof _ === "function" ? _ : constant$1(_), histogram) : value;
19498   };
19499
19500   histogram.domain = function(_) {
19501     return arguments.length ? (domain = typeof _ === "function" ? _ : constant$1([_[0], _[1]]), histogram) : domain;
19502   };
19503
19504   histogram.thresholds = function(_) {
19505     return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant$1(slice.call(_)) : constant$1(_), histogram) : threshold;
19506   };
19507
19508   return histogram;
19509 };
19510
19511 var threshold = function(array, p, f) {
19512   if (f == null) f = number;
19513   if (!(n = array.length)) return;
19514   if ((p = +p) <= 0 || n < 2) return +f(array[0], 0, array);
19515   if (p >= 1) return +f(array[n - 1], n - 1, array);
19516   var n,
19517       h = (n - 1) * p,
19518       i = Math.floor(h),
19519       a = +f(array[i], i, array),
19520       b = +f(array[i + 1], i + 1, array);
19521   return a + (b - a) * (h - i);
19522 };
19523
19524 var freedmanDiaconis = function(values, min, max) {
19525   values = map.call(values, number).sort(ascending);
19526   return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3)));
19527 };
19528
19529 var scott = function(values, min, max) {
19530   return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
19531 };
19532
19533 var max = function(array, f) {
19534   var i = -1,
19535       n = array.length,
19536       a,
19537       b;
19538
19539   if (f == null) {
19540     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19541     while (++i < n) if ((b = array[i]) != null && b > a) a = b;
19542   }
19543
19544   else {
19545     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19546     while (++i < n) if ((b = f(array[i], i, array)) != null && b > a) a = b;
19547   }
19548
19549   return a;
19550 };
19551
19552 var mean = function(array, f) {
19553   var s = 0,
19554       n = array.length,
19555       a,
19556       i = -1,
19557       j = n;
19558
19559   if (f == null) {
19560     while (++i < n) if (!isNaN(a = number(array[i]))) s += a; else --j;
19561   }
19562
19563   else {
19564     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) s += a; else --j;
19565   }
19566
19567   if (j) return s / j;
19568 };
19569
19570 var median = function(array, f) {
19571   var numbers = [],
19572       n = array.length,
19573       a,
19574       i = -1;
19575
19576   if (f == null) {
19577     while (++i < n) if (!isNaN(a = number(array[i]))) numbers.push(a);
19578   }
19579
19580   else {
19581     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) numbers.push(a);
19582   }
19583
19584   return threshold(numbers.sort(ascending), 0.5);
19585 };
19586
19587 var merge = function(arrays) {
19588   var n = arrays.length,
19589       m,
19590       i = -1,
19591       j = 0,
19592       merged,
19593       array;
19594
19595   while (++i < n) j += arrays[i].length;
19596   merged = new Array(j);
19597
19598   while (--n >= 0) {
19599     array = arrays[n];
19600     m = array.length;
19601     while (--m >= 0) {
19602       merged[--j] = array[m];
19603     }
19604   }
19605
19606   return merged;
19607 };
19608
19609 var min = function(array, f) {
19610   var i = -1,
19611       n = array.length,
19612       a,
19613       b;
19614
19615   if (f == null) {
19616     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19617     while (++i < n) if ((b = array[i]) != null && a > b) a = b;
19618   }
19619
19620   else {
19621     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19622     while (++i < n) if ((b = f(array[i], i, array)) != null && a > b) a = b;
19623   }
19624
19625   return a;
19626 };
19627
19628 var pairs = function(array) {
19629   var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
19630   while (i < n) pairs[i] = [p, p = array[++i]];
19631   return pairs;
19632 };
19633
19634 var permute = function(array, indexes) {
19635   var i = indexes.length, permutes = new Array(i);
19636   while (i--) permutes[i] = array[indexes[i]];
19637   return permutes;
19638 };
19639
19640 var scan = function(array, compare) {
19641   if (!(n = array.length)) return;
19642   var i = 0,
19643       n,
19644       j = 0,
19645       xi,
19646       xj = array[j];
19647
19648   if (!compare) compare = ascending;
19649
19650   while (++i < n) if (compare(xi = array[i], xj) < 0 || compare(xj, xj) !== 0) xj = xi, j = i;
19651
19652   if (compare(xj, xj) === 0) return j;
19653 };
19654
19655 var shuffle = function(array, i0, i1) {
19656   var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
19657       t,
19658       i;
19659
19660   while (m) {
19661     i = Math.random() * m-- | 0;
19662     t = array[m + i0];
19663     array[m + i0] = array[i + i0];
19664     array[i + i0] = t;
19665   }
19666
19667   return array;
19668 };
19669
19670 var sum = function(array, f) {
19671   var s = 0,
19672       n = array.length,
19673       a,
19674       i = -1;
19675
19676   if (f == null) {
19677     while (++i < n) if (a = +array[i]) s += a; // Note: zero and null are equivalent.
19678   }
19679
19680   else {
19681     while (++i < n) if (a = +f(array[i], i, array)) s += a;
19682   }
19683
19684   return s;
19685 };
19686
19687 var transpose = function(matrix) {
19688   if (!(n = matrix.length)) return [];
19689   for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
19690     for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
19691       row[j] = matrix[j][i];
19692     }
19693   }
19694   return transpose;
19695 };
19696
19697 function length(d) {
19698   return d.length;
19699 }
19700
19701 var zip = function() {
19702   return transpose(arguments);
19703 };
19704
19705 var prefix = "$";
19706
19707 function Map() {}
19708
19709 Map.prototype = map$1.prototype = {
19710   constructor: Map,
19711   has: function(key) {
19712     return (prefix + key) in this;
19713   },
19714   get: function(key) {
19715     return this[prefix + key];
19716   },
19717   set: function(key, value) {
19718     this[prefix + key] = value;
19719     return this;
19720   },
19721   remove: function(key) {
19722     var property = prefix + key;
19723     return property in this && delete this[property];
19724   },
19725   clear: function() {
19726     for (var property in this) if (property[0] === prefix) delete this[property];
19727   },
19728   keys: function() {
19729     var keys = [];
19730     for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
19731     return keys;
19732   },
19733   values: function() {
19734     var values = [];
19735     for (var property in this) if (property[0] === prefix) values.push(this[property]);
19736     return values;
19737   },
19738   entries: function() {
19739     var entries = [];
19740     for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
19741     return entries;
19742   },
19743   size: function() {
19744     var size = 0;
19745     for (var property in this) if (property[0] === prefix) ++size;
19746     return size;
19747   },
19748   empty: function() {
19749     for (var property in this) if (property[0] === prefix) return false;
19750     return true;
19751   },
19752   each: function(f) {
19753     for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
19754   }
19755 };
19756
19757 function map$1(object, f) {
19758   var map = new Map;
19759
19760   // Copy constructor.
19761   if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
19762
19763   // Index array by numeric index or specified key function.
19764   else if (Array.isArray(object)) {
19765     var i = -1,
19766         n = object.length,
19767         o;
19768
19769     if (f == null) while (++i < n) map.set(i, object[i]);
19770     else while (++i < n) map.set(f(o = object[i], i, object), o);
19771   }
19772
19773   // Convert object to map.
19774   else if (object) for (var key in object) map.set(key, object[key]);
19775
19776   return map;
19777 }
19778
19779 var nest = function() {
19780   var keys = [],
19781       sortKeys = [],
19782       sortValues,
19783       rollup,
19784       nest;
19785
19786   function apply(array, depth, createResult, setResult) {
19787     if (depth >= keys.length) return rollup != null
19788         ? rollup(array) : (sortValues != null
19789         ? array.sort(sortValues)
19790         : array);
19791
19792     var i = -1,
19793         n = array.length,
19794         key = keys[depth++],
19795         keyValue,
19796         value,
19797         valuesByKey = map$1(),
19798         values,
19799         result = createResult();
19800
19801     while (++i < n) {
19802       if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
19803         values.push(value);
19804       } else {
19805         valuesByKey.set(keyValue, [value]);
19806       }
19807     }
19808
19809     valuesByKey.each(function(values, key) {
19810       setResult(result, key, apply(values, depth, createResult, setResult));
19811     });
19812
19813     return result;
19814   }
19815
19816   function entries(map, depth) {
19817     if (++depth > keys.length) return map;
19818     var array, sortKey = sortKeys[depth - 1];
19819     if (rollup != null && depth >= keys.length) array = map.entries();
19820     else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
19821     return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
19822   }
19823
19824   return nest = {
19825     object: function(array) { return apply(array, 0, createObject, setObject); },
19826     map: function(array) { return apply(array, 0, createMap, setMap); },
19827     entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
19828     key: function(d) { keys.push(d); return nest; },
19829     sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
19830     sortValues: function(order) { sortValues = order; return nest; },
19831     rollup: function(f) { rollup = f; return nest; }
19832   };
19833 };
19834
19835 function createObject() {
19836   return {};
19837 }
19838
19839 function setObject(object, key, value) {
19840   object[key] = value;
19841 }
19842
19843 function createMap() {
19844   return map$1();
19845 }
19846
19847 function setMap(map, key, value) {
19848   map.set(key, value);
19849 }
19850
19851 function Set() {}
19852
19853 var proto = map$1.prototype;
19854
19855 Set.prototype = set.prototype = {
19856   constructor: Set,
19857   has: proto.has,
19858   add: function(value) {
19859     value += "";
19860     this[prefix + value] = value;
19861     return this;
19862   },
19863   remove: proto.remove,
19864   clear: proto.clear,
19865   values: proto.keys,
19866   size: proto.size,
19867   empty: proto.empty,
19868   each: proto.each
19869 };
19870
19871 function set(object, f) {
19872   var set = new Set;
19873
19874   // Copy constructor.
19875   if (object instanceof Set) object.each(function(value) { set.add(value); });
19876
19877   // Otherwise, assume it’s an array.
19878   else if (object) {
19879     var i = -1, n = object.length;
19880     if (f == null) while (++i < n) set.add(object[i]);
19881     else while (++i < n) set.add(f(object[i], i, object));
19882   }
19883
19884   return set;
19885 }
19886
19887 var keys = function(map) {
19888   var keys = [];
19889   for (var key in map) keys.push(key);
19890   return keys;
19891 };
19892
19893 var values = function(map) {
19894   var values = [];
19895   for (var key in map) values.push(map[key]);
19896   return values;
19897 };
19898
19899 var entries = function(map) {
19900   var entries = [];
19901   for (var key in map) entries.push({key: key, value: map[key]});
19902   return entries;
19903 };
19904
19905 var uniform = function(min, max) {
19906   min = min == null ? 0 : +min;
19907   max = max == null ? 1 : +max;
19908   if (arguments.length === 1) max = min, min = 0;
19909   else max -= min;
19910   return function() {
19911     return Math.random() * max + min;
19912   };
19913 };
19914
19915 var normal = function(mu, sigma) {
19916   var x, r;
19917   mu = mu == null ? 0 : +mu;
19918   sigma = sigma == null ? 1 : +sigma;
19919   return function() {
19920     var y;
19921
19922     // If available, use the second previously-generated uniform random.
19923     if (x != null) y = x, x = null;
19924
19925     // Otherwise, generate a new x and y.
19926     else do {
19927       x = Math.random() * 2 - 1;
19928       y = Math.random() * 2 - 1;
19929       r = x * x + y * y;
19930     } while (!r || r > 1);
19931
19932     return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
19933   };
19934 };
19935
19936 var logNormal = function() {
19937   var randomNormal = normal.apply(this, arguments);
19938   return function() {
19939     return Math.exp(randomNormal());
19940   };
19941 };
19942
19943 var irwinHall = function(n) {
19944   return function() {
19945     for (var sum = 0, i = 0; i < n; ++i) sum += Math.random();
19946     return sum;
19947   };
19948 };
19949
19950 var bates = function(n) {
19951   var randomIrwinHall = irwinHall(n);
19952   return function() {
19953     return randomIrwinHall() / n;
19954   };
19955 };
19956
19957 var exponential = function(lambda) {
19958   return function() {
19959     return -Math.log(1 - Math.random()) / lambda;
19960   };
19961 };
19962
19963 function linear(t) {
19964   return +t;
19965 }
19966
19967 function quadIn(t) {
19968   return t * t;
19969 }
19970
19971 function quadOut(t) {
19972   return t * (2 - t);
19973 }
19974
19975 function quadInOut(t) {
19976   return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
19977 }
19978
19979 function cubicIn(t) {
19980   return t * t * t;
19981 }
19982
19983 function cubicOut(t) {
19984   return --t * t * t + 1;
19985 }
19986
19987 function cubicInOut(t) {
19988   return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
19989 }
19990
19991 var exponent = 3;
19992
19993 var polyIn = (function custom(e) {
19994   e = +e;
19995
19996   function polyIn(t) {
19997     return Math.pow(t, e);
19998   }
19999
20000   polyIn.exponent = custom;
20001
20002   return polyIn;
20003 })(exponent);
20004
20005 var polyOut = (function custom(e) {
20006   e = +e;
20007
20008   function polyOut(t) {
20009     return 1 - Math.pow(1 - t, e);
20010   }
20011
20012   polyOut.exponent = custom;
20013
20014   return polyOut;
20015 })(exponent);
20016
20017 var polyInOut = (function custom(e) {
20018   e = +e;
20019
20020   function polyInOut(t) {
20021     return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
20022   }
20023
20024   polyInOut.exponent = custom;
20025
20026   return polyInOut;
20027 })(exponent);
20028
20029 var pi = Math.PI;
20030 var halfPi = pi / 2;
20031
20032 function sinIn(t) {
20033   return 1 - Math.cos(t * halfPi);
20034 }
20035
20036 function sinOut(t) {
20037   return Math.sin(t * halfPi);
20038 }
20039
20040 function sinInOut(t) {
20041   return (1 - Math.cos(pi * t)) / 2;
20042 }
20043
20044 function expIn(t) {
20045   return Math.pow(2, 10 * t - 10);
20046 }
20047
20048 function expOut(t) {
20049   return 1 - Math.pow(2, -10 * t);
20050 }
20051
20052 function expInOut(t) {
20053   return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
20054 }
20055
20056 function circleIn(t) {
20057   return 1 - Math.sqrt(1 - t * t);
20058 }
20059
20060 function circleOut(t) {
20061   return Math.sqrt(1 - --t * t);
20062 }
20063
20064 function circleInOut(t) {
20065   return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
20066 }
20067
20068 var b1 = 4 / 11;
20069 var b2 = 6 / 11;
20070 var b3 = 8 / 11;
20071 var b4 = 3 / 4;
20072 var b5 = 9 / 11;
20073 var b6 = 10 / 11;
20074 var b7 = 15 / 16;
20075 var b8 = 21 / 22;
20076 var b9 = 63 / 64;
20077 var b0 = 1 / b1 / b1;
20078
20079 function bounceIn(t) {
20080   return 1 - bounceOut(1 - t);
20081 }
20082
20083 function bounceOut(t) {
20084   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;
20085 }
20086
20087 function bounceInOut(t) {
20088   return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2;
20089 }
20090
20091 var overshoot = 1.70158;
20092
20093 var backIn = (function custom(s) {
20094   s = +s;
20095
20096   function backIn(t) {
20097     return t * t * ((s + 1) * t - s);
20098   }
20099
20100   backIn.overshoot = custom;
20101
20102   return backIn;
20103 })(overshoot);
20104
20105 var backOut = (function custom(s) {
20106   s = +s;
20107
20108   function backOut(t) {
20109     return --t * t * ((s + 1) * t + s) + 1;
20110   }
20111
20112   backOut.overshoot = custom;
20113
20114   return backOut;
20115 })(overshoot);
20116
20117 var backInOut = (function custom(s) {
20118   s = +s;
20119
20120   function backInOut(t) {
20121     return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
20122   }
20123
20124   backInOut.overshoot = custom;
20125
20126   return backInOut;
20127 })(overshoot);
20128
20129 var tau = 2 * Math.PI;
20130 var amplitude = 1;
20131 var period = 0.3;
20132
20133 var elasticIn = (function custom(a, p) {
20134   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20135
20136   function elasticIn(t) {
20137     return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
20138   }
20139
20140   elasticIn.amplitude = function(a) { return custom(a, p * tau); };
20141   elasticIn.period = function(p) { return custom(a, p); };
20142
20143   return elasticIn;
20144 })(amplitude, period);
20145
20146 var elasticOut = (function custom(a, p) {
20147   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20148
20149   function elasticOut(t) {
20150     return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
20151   }
20152
20153   elasticOut.amplitude = function(a) { return custom(a, p * tau); };
20154   elasticOut.period = function(p) { return custom(a, p); };
20155
20156   return elasticOut;
20157 })(amplitude, period);
20158
20159 var elasticInOut = (function custom(a, p) {
20160   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20161
20162   function elasticInOut(t) {
20163     return ((t = t * 2 - 1) < 0
20164         ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
20165         : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
20166   }
20167
20168   elasticInOut.amplitude = function(a) { return custom(a, p * tau); };
20169   elasticInOut.period = function(p) { return custom(a, p); };
20170
20171   return elasticInOut;
20172 })(amplitude, period);
20173
20174 var d3polygonArea = function(polygon) {
20175   var i = -1,
20176       n = polygon.length,
20177       a,
20178       b = polygon[n - 1],
20179       area = 0;
20180
20181   while (++i < n) {
20182     a = b;
20183     b = polygon[i];
20184     area += a[1] * b[0] - a[0] * b[1];
20185   }
20186
20187   return area / 2;
20188 };
20189
20190 var d3polygonCentroid = function(polygon) {
20191   var i = -1,
20192       n = polygon.length,
20193       x = 0,
20194       y = 0,
20195       a,
20196       b = polygon[n - 1],
20197       c,
20198       k = 0;
20199
20200   while (++i < n) {
20201     a = b;
20202     b = polygon[i];
20203     k += c = a[0] * b[1] - b[0] * a[1];
20204     x += (a[0] + b[0]) * c;
20205     y += (a[1] + b[1]) * c;
20206   }
20207
20208   return k *= 3, [x / k, y / k];
20209 };
20210
20211 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
20212 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
20213 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
20214 // negative if clockwise, and zero if the points are collinear.
20215 var cross = function(a, b, c) {
20216   return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
20217 };
20218
20219 function lexicographicOrder(a, b) {
20220   return a[0] - b[0] || a[1] - b[1];
20221 }
20222
20223 // Computes the upper convex hull per the monotone chain algorithm.
20224 // Assumes points.length >= 3, is sorted by x, unique in y.
20225 // Returns an array of indices into points in left-to-right order.
20226 function computeUpperHullIndexes(points) {
20227   var n = points.length,
20228       indexes = [0, 1],
20229       size = 2;
20230
20231   for (var i = 2; i < n; ++i) {
20232     while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
20233     indexes[size++] = i;
20234   }
20235
20236   return indexes.slice(0, size); // remove popped points
20237 }
20238
20239 var d3polygonHull = function(points) {
20240   if ((n = points.length) < 3) return null;
20241
20242   var i,
20243       n,
20244       sortedPoints = new Array(n),
20245       flippedPoints = new Array(n);
20246
20247   for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
20248   sortedPoints.sort(lexicographicOrder);
20249   for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
20250
20251   var upperIndexes = computeUpperHullIndexes(sortedPoints),
20252       lowerIndexes = computeUpperHullIndexes(flippedPoints);
20253
20254   // Construct the hull polygon, removing possible duplicate endpoints.
20255   var skipLeft = lowerIndexes[0] === upperIndexes[0],
20256       skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
20257       hull = [];
20258
20259   // Add upper hull in right-to-l order.
20260   // Then add lower hull in left-to-right order.
20261   for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
20262   for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
20263
20264   return hull;
20265 };
20266
20267 var contains = function(polygon, point) {
20268   var n = polygon.length,
20269       p = polygon[n - 1],
20270       x = point[0], y = point[1],
20271       x0 = p[0], y0 = p[1],
20272       x1, y1,
20273       inside = false;
20274
20275   for (var i = 0; i < n; ++i) {
20276     p = polygon[i], x1 = p[0], y1 = p[1];
20277     if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
20278     x0 = x1, y0 = y1;
20279   }
20280
20281   return inside;
20282 };
20283
20284 var length$1 = function(polygon) {
20285   var i = -1,
20286       n = polygon.length,
20287       b = polygon[n - 1],
20288       xa,
20289       ya,
20290       xb = b[0],
20291       yb = b[1],
20292       perimeter = 0;
20293
20294   while (++i < n) {
20295     xa = xb;
20296     ya = yb;
20297     b = polygon[i];
20298     xb = b[0];
20299     yb = b[1];
20300     xa -= xb;
20301     ya -= yb;
20302     perimeter += Math.sqrt(xa * xa + ya * ya);
20303   }
20304
20305   return perimeter;
20306 };
20307
20308 var pi$1 = Math.PI;
20309 var tau$1 = 2 * pi$1;
20310 var epsilon = 1e-6;
20311 var tauEpsilon = tau$1 - epsilon;
20312
20313 function Path() {
20314   this._x0 = this._y0 = // start of current subpath
20315   this._x1 = this._y1 = null; // end of current subpath
20316   this._ = [];
20317 }
20318
20319 function path() {
20320   return new Path;
20321 }
20322
20323 Path.prototype = path.prototype = {
20324   constructor: Path,
20325   moveTo: function(x, y) {
20326     this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y);
20327   },
20328   closePath: function() {
20329     if (this._x1 !== null) {
20330       this._x1 = this._x0, this._y1 = this._y0;
20331       this._.push("Z");
20332     }
20333   },
20334   lineTo: function(x, y) {
20335     this._.push("L", this._x1 = +x, ",", this._y1 = +y);
20336   },
20337   quadraticCurveTo: function(x1, y1, x, y) {
20338     this._.push("Q", +x1, ",", +y1, ",", this._x1 = +x, ",", this._y1 = +y);
20339   },
20340   bezierCurveTo: function(x1, y1, x2, y2, x, y) {
20341     this._.push("C", +x1, ",", +y1, ",", +x2, ",", +y2, ",", this._x1 = +x, ",", this._y1 = +y);
20342   },
20343   arcTo: function(x1, y1, x2, y2, r) {
20344     x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
20345     var x0 = this._x1,
20346         y0 = this._y1,
20347         x21 = x2 - x1,
20348         y21 = y2 - y1,
20349         x01 = x0 - x1,
20350         y01 = y0 - y1,
20351         l01_2 = x01 * x01 + y01 * y01;
20352
20353     // Is the radius negative? Error.
20354     if (r < 0) throw new Error("negative radius: " + r);
20355
20356     // Is this path empty? Move to (x1,y1).
20357     if (this._x1 === null) {
20358       this._.push(
20359         "M", this._x1 = x1, ",", this._y1 = y1
20360       );
20361     }
20362
20363     // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
20364     else if (!(l01_2 > epsilon)) {}
20365
20366     // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
20367     // Equivalently, is (x1,y1) coincident with (x2,y2)?
20368     // Or, is the radius zero? Line to (x1,y1).
20369     else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {
20370       this._.push(
20371         "L", this._x1 = x1, ",", this._y1 = y1
20372       );
20373     }
20374
20375     // Otherwise, draw an arc!
20376     else {
20377       var x20 = x2 - x0,
20378           y20 = y2 - y0,
20379           l21_2 = x21 * x21 + y21 * y21,
20380           l20_2 = x20 * x20 + y20 * y20,
20381           l21 = Math.sqrt(l21_2),
20382           l01 = Math.sqrt(l01_2),
20383           l = r * Math.tan((pi$1 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
20384           t01 = l / l01,
20385           t21 = l / l21;
20386
20387       // If the start tangent is not coincident with (x0,y0), line to.
20388       if (Math.abs(t01 - 1) > epsilon) {
20389         this._.push(
20390           "L", x1 + t01 * x01, ",", y1 + t01 * y01
20391         );
20392       }
20393
20394       this._.push(
20395         "A", r, ",", r, ",0,0,", +(y01 * x20 > x01 * y20), ",", this._x1 = x1 + t21 * x21, ",", this._y1 = y1 + t21 * y21
20396       );
20397     }
20398   },
20399   arc: function(x, y, r, a0, a1, ccw) {
20400     x = +x, y = +y, r = +r;
20401     var dx = r * Math.cos(a0),
20402         dy = r * Math.sin(a0),
20403         x0 = x + dx,
20404         y0 = y + dy,
20405         cw = 1 ^ ccw,
20406         da = ccw ? a0 - a1 : a1 - a0;
20407
20408     // Is the radius negative? Error.
20409     if (r < 0) throw new Error("negative radius: " + r);
20410
20411     // Is this path empty? Move to (x0,y0).
20412     if (this._x1 === null) {
20413       this._.push(
20414         "M", x0, ",", y0
20415       );
20416     }
20417
20418     // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
20419     else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
20420       this._.push(
20421         "L", x0, ",", y0
20422       );
20423     }
20424
20425     // Is this arc empty? We’re done.
20426     if (!r) return;
20427
20428     // Is this a complete circle? Draw two arcs to complete the circle.
20429     if (da > tauEpsilon) {
20430       this._.push(
20431         "A", r, ",", r, ",0,1,", cw, ",", x - dx, ",", y - dy,
20432         "A", r, ",", r, ",0,1,", cw, ",", this._x1 = x0, ",", this._y1 = y0
20433       );
20434     }
20435
20436     // Otherwise, draw an arc!
20437     else {
20438       if (da < 0) da = da % tau$1 + tau$1;
20439       this._.push(
20440         "A", r, ",", r, ",0,", +(da >= pi$1), ",", cw, ",", this._x1 = x + r * Math.cos(a1), ",", this._y1 = y + r * Math.sin(a1)
20441       );
20442     }
20443   },
20444   rect: function(x, y, w, h) {
20445     this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y, "h", +w, "v", +h, "h", -w, "Z");
20446   },
20447   toString: function() {
20448     return this._.join("");
20449   }
20450 };
20451
20452 var tree_add = function(d) {
20453   var x = +this._x.call(null, d),
20454       y = +this._y.call(null, d);
20455   return add(this.cover(x, y), x, y, d);
20456 };
20457
20458 function add(tree, x, y, d) {
20459   if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
20460
20461   var parent,
20462       node = tree._root,
20463       leaf = {data: d},
20464       x0 = tree._x0,
20465       y0 = tree._y0,
20466       x1 = tree._x1,
20467       y1 = tree._y1,
20468       xm,
20469       ym,
20470       xp,
20471       yp,
20472       right,
20473       bottom,
20474       i,
20475       j;
20476
20477   // If the tree is empty, initialize the root as a leaf.
20478   if (!node) return tree._root = leaf, tree;
20479
20480   // Find the existing leaf for the new point, or add it.
20481   while (node.length) {
20482     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20483     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20484     if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
20485   }
20486
20487   // Is the new point is exactly coincident with the existing point?
20488   xp = +tree._x.call(null, node.data);
20489   yp = +tree._y.call(null, node.data);
20490   if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
20491
20492   // Otherwise, split the leaf node until the old and new point are separated.
20493   do {
20494     parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
20495     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20496     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20497   } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
20498   return parent[j] = node, parent[i] = leaf, tree;
20499 }
20500
20501 function addAll(data) {
20502   var d, i, n = data.length,
20503       x,
20504       y,
20505       xz = new Array(n),
20506       yz = new Array(n),
20507       x0 = Infinity,
20508       y0 = Infinity,
20509       x1 = -Infinity,
20510       y1 = -Infinity;
20511
20512   // Compute the points and their extent.
20513   for (i = 0; i < n; ++i) {
20514     if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
20515     xz[i] = x;
20516     yz[i] = y;
20517     if (x < x0) x0 = x;
20518     if (x > x1) x1 = x;
20519     if (y < y0) y0 = y;
20520     if (y > y1) y1 = y;
20521   }
20522
20523   // If there were no (valid) points, inherit the existing extent.
20524   if (x1 < x0) x0 = this._x0, x1 = this._x1;
20525   if (y1 < y0) y0 = this._y0, y1 = this._y1;
20526
20527   // Expand the tree to cover the new points.
20528   this.cover(x0, y0).cover(x1, y1);
20529
20530   // Add the new points.
20531   for (i = 0; i < n; ++i) {
20532     add(this, xz[i], yz[i], data[i]);
20533   }
20534
20535   return this;
20536 }
20537
20538 var tree_cover = function(x, y) {
20539   if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
20540
20541   var x0 = this._x0,
20542       y0 = this._y0,
20543       x1 = this._x1,
20544       y1 = this._y1;
20545
20546   // If the quadtree has no extent, initialize them.
20547   // Integer extent are necessary so that if we later double the extent,
20548   // the existing quadrant boundaries don’t change due to floating point error!
20549   if (isNaN(x0)) {
20550     x1 = (x0 = Math.floor(x)) + 1;
20551     y1 = (y0 = Math.floor(y)) + 1;
20552   }
20553
20554   // Otherwise, double repeatedly to cover.
20555   else if (x0 > x || x > x1 || y0 > y || y > y1) {
20556     var z = x1 - x0,
20557         node = this._root,
20558         parent,
20559         i;
20560
20561     switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
20562       case 0: {
20563         do parent = new Array(4), parent[i] = node, node = parent;
20564         while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
20565         break;
20566       }
20567       case 1: {
20568         do parent = new Array(4), parent[i] = node, node = parent;
20569         while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
20570         break;
20571       }
20572       case 2: {
20573         do parent = new Array(4), parent[i] = node, node = parent;
20574         while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
20575         break;
20576       }
20577       case 3: {
20578         do parent = new Array(4), parent[i] = node, node = parent;
20579         while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
20580         break;
20581       }
20582     }
20583
20584     if (this._root && this._root.length) this._root = node;
20585   }
20586
20587   // If the quadtree covers the point already, just return.
20588   else return this;
20589
20590   this._x0 = x0;
20591   this._y0 = y0;
20592   this._x1 = x1;
20593   this._y1 = y1;
20594   return this;
20595 };
20596
20597 var tree_data = function() {
20598   var data = [];
20599   this.visit(function(node) {
20600     if (!node.length) do data.push(node.data); while (node = node.next)
20601   });
20602   return data;
20603 };
20604
20605 var tree_extent = function(_) {
20606   return arguments.length
20607       ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
20608       : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
20609 };
20610
20611 var Quad = function(node, x0, y0, x1, y1) {
20612   this.node = node;
20613   this.x0 = x0;
20614   this.y0 = y0;
20615   this.x1 = x1;
20616   this.y1 = y1;
20617 };
20618
20619 var tree_find = function(x, y, radius) {
20620   var data,
20621       x0 = this._x0,
20622       y0 = this._y0,
20623       x1,
20624       y1,
20625       x2,
20626       y2,
20627       x3 = this._x1,
20628       y3 = this._y1,
20629       quads = [],
20630       node = this._root,
20631       q,
20632       i;
20633
20634   if (node) quads.push(new Quad(node, x0, y0, x3, y3));
20635   if (radius == null) radius = Infinity;
20636   else {
20637     x0 = x - radius, y0 = y - radius;
20638     x3 = x + radius, y3 = y + radius;
20639     radius *= radius;
20640   }
20641
20642   while (q = quads.pop()) {
20643
20644     // Stop searching if this quadrant can’t contain a closer node.
20645     if (!(node = q.node)
20646         || (x1 = q.x0) > x3
20647         || (y1 = q.y0) > y3
20648         || (x2 = q.x1) < x0
20649         || (y2 = q.y1) < y0) continue;
20650
20651     // Bisect the current quadrant.
20652     if (node.length) {
20653       var xm = (x1 + x2) / 2,
20654           ym = (y1 + y2) / 2;
20655
20656       quads.push(
20657         new Quad(node[3], xm, ym, x2, y2),
20658         new Quad(node[2], x1, ym, xm, y2),
20659         new Quad(node[1], xm, y1, x2, ym),
20660         new Quad(node[0], x1, y1, xm, ym)
20661       );
20662
20663       // Visit the closest quadrant first.
20664       if (i = (y >= ym) << 1 | (x >= xm)) {
20665         q = quads[quads.length - 1];
20666         quads[quads.length - 1] = quads[quads.length - 1 - i];
20667         quads[quads.length - 1 - i] = q;
20668       }
20669     }
20670
20671     // Visit this point. (Visiting coincident points isn’t necessary!)
20672     else {
20673       var dx = x - +this._x.call(null, node.data),
20674           dy = y - +this._y.call(null, node.data),
20675           d2 = dx * dx + dy * dy;
20676       if (d2 < radius) {
20677         var d = Math.sqrt(radius = d2);
20678         x0 = x - d, y0 = y - d;
20679         x3 = x + d, y3 = y + d;
20680         data = node.data;
20681       }
20682     }
20683   }
20684
20685   return data;
20686 };
20687
20688 var tree_remove = function(d) {
20689   if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
20690
20691   var parent,
20692       node = this._root,
20693       retainer,
20694       previous,
20695       next,
20696       x0 = this._x0,
20697       y0 = this._y0,
20698       x1 = this._x1,
20699       y1 = this._y1,
20700       x,
20701       y,
20702       xm,
20703       ym,
20704       right,
20705       bottom,
20706       i,
20707       j;
20708
20709   // If the tree is empty, initialize the root as a leaf.
20710   if (!node) return this;
20711
20712   // Find the leaf node for the point.
20713   // While descending, also retain the deepest parent with a non-removed sibling.
20714   if (node.length) while (true) {
20715     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20716     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20717     if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
20718     if (!node.length) break;
20719     if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
20720   }
20721
20722   // Find the point to remove.
20723   while (node.data !== d) if (!(previous = node, node = node.next)) return this;
20724   if (next = node.next) delete node.next;
20725
20726   // If there are multiple coincident points, remove just the point.
20727   if (previous) return (next ? previous.next = next : delete previous.next), this;
20728
20729   // If this is the root point, remove it.
20730   if (!parent) return this._root = next, this;
20731
20732   // Remove this leaf.
20733   next ? parent[i] = next : delete parent[i];
20734
20735   // If the parent now contains exactly one leaf, collapse superfluous parents.
20736   if ((node = parent[0] || parent[1] || parent[2] || parent[3])
20737       && node === (parent[3] || parent[2] || parent[1] || parent[0])
20738       && !node.length) {
20739     if (retainer) retainer[j] = node;
20740     else this._root = node;
20741   }
20742
20743   return this;
20744 };
20745
20746 function removeAll(data) {
20747   for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
20748   return this;
20749 }
20750
20751 var tree_root = function() {
20752   return this._root;
20753 };
20754
20755 var tree_size = function() {
20756   var size = 0;
20757   this.visit(function(node) {
20758     if (!node.length) do ++size; while (node = node.next)
20759   });
20760   return size;
20761 };
20762
20763 var tree_visit = function(callback) {
20764   var quads = [], q, node = this._root, child, x0, y0, x1, y1;
20765   if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
20766   while (q = quads.pop()) {
20767     if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
20768       var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
20769       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
20770       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
20771       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
20772       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
20773     }
20774   }
20775   return this;
20776 };
20777
20778 var tree_visitAfter = function(callback) {
20779   var quads = [], next = [], q;
20780   if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
20781   while (q = quads.pop()) {
20782     var node = q.node;
20783     if (node.length) {
20784       var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
20785       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
20786       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
20787       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
20788       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
20789     }
20790     next.push(q);
20791   }
20792   while (q = next.pop()) {
20793     callback(q.node, q.x0, q.y0, q.x1, q.y1);
20794   }
20795   return this;
20796 };
20797
20798 function defaultX(d) {
20799   return d[0];
20800 }
20801
20802 var tree_x = function(_) {
20803   return arguments.length ? (this._x = _, this) : this._x;
20804 };
20805
20806 function defaultY(d) {
20807   return d[1];
20808 }
20809
20810 var tree_y = function(_) {
20811   return arguments.length ? (this._y = _, this) : this._y;
20812 };
20813
20814 function quadtree(nodes, x, y) {
20815   var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
20816   return nodes == null ? tree : tree.addAll(nodes);
20817 }
20818
20819 function Quadtree(x, y, x0, y0, x1, y1) {
20820   this._x = x;
20821   this._y = y;
20822   this._x0 = x0;
20823   this._y0 = y0;
20824   this._x1 = x1;
20825   this._y1 = y1;
20826   this._root = undefined;
20827 }
20828
20829 function leaf_copy(leaf) {
20830   var copy = {data: leaf.data}, next = copy;
20831   while (leaf = leaf.next) next = next.next = {data: leaf.data};
20832   return copy;
20833 }
20834
20835 var treeProto = quadtree.prototype = Quadtree.prototype;
20836
20837 treeProto.copy = function() {
20838   var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
20839       node = this._root,
20840       nodes,
20841       child;
20842
20843   if (!node) return copy;
20844
20845   if (!node.length) return copy._root = leaf_copy(node), copy;
20846
20847   nodes = [{source: node, target: copy._root = new Array(4)}];
20848   while (node = nodes.pop()) {
20849     for (var i = 0; i < 4; ++i) {
20850       if (child = node.source[i]) {
20851         if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
20852         else node.target[i] = leaf_copy(child);
20853       }
20854     }
20855   }
20856
20857   return copy;
20858 };
20859
20860 treeProto.add = tree_add;
20861 treeProto.addAll = addAll;
20862 treeProto.cover = tree_cover;
20863 treeProto.data = tree_data;
20864 treeProto.extent = tree_extent;
20865 treeProto.find = tree_find;
20866 treeProto.remove = tree_remove;
20867 treeProto.removeAll = removeAll;
20868 treeProto.root = tree_root;
20869 treeProto.size = tree_size;
20870 treeProto.visit = tree_visit;
20871 treeProto.visitAfter = tree_visitAfter;
20872 treeProto.x = tree_x;
20873 treeProto.y = tree_y;
20874
20875 var slice$1 = [].slice;
20876
20877 var noabort = {};
20878
20879 function Queue(size) {
20880   if (!(size >= 1)) throw new Error;
20881   this._size = size;
20882   this._call =
20883   this._error = null;
20884   this._tasks = [];
20885   this._data = [];
20886   this._waiting =
20887   this._active =
20888   this._ended =
20889   this._start = 0; // inside a synchronous task callback?
20890 }
20891
20892 Queue.prototype = queue.prototype = {
20893   constructor: Queue,
20894   defer: function(callback) {
20895     if (typeof callback !== "function" || this._call) throw new Error;
20896     if (this._error != null) return this;
20897     var t = slice$1.call(arguments, 1);
20898     t.push(callback);
20899     ++this._waiting, this._tasks.push(t);
20900     poke(this);
20901     return this;
20902   },
20903   abort: function() {
20904     if (this._error == null) abort(this, new Error("abort"));
20905     return this;
20906   },
20907   await: function(callback) {
20908     if (typeof callback !== "function" || this._call) throw new Error;
20909     this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
20910     maybeNotify(this);
20911     return this;
20912   },
20913   awaitAll: function(callback) {
20914     if (typeof callback !== "function" || this._call) throw new Error;
20915     this._call = callback;
20916     maybeNotify(this);
20917     return this;
20918   }
20919 };
20920
20921 function poke(q) {
20922   if (!q._start) {
20923     try { start(q); } // let the current task complete
20924     catch (e) {
20925       if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
20926       else if (!q._data) throw e; // await callback errored synchronously
20927     }
20928   }
20929 }
20930
20931 function start(q) {
20932   while (q._start = q._waiting && q._active < q._size) {
20933     var i = q._ended + q._active,
20934         t = q._tasks[i],
20935         j = t.length - 1,
20936         c = t[j];
20937     t[j] = end(q, i);
20938     --q._waiting, ++q._active;
20939     t = c.apply(null, t);
20940     if (!q._tasks[i]) continue; // task finished synchronously
20941     q._tasks[i] = t || noabort;
20942   }
20943 }
20944
20945 function end(q, i) {
20946   return function(e, r) {
20947     if (!q._tasks[i]) return; // ignore multiple callbacks
20948     --q._active, ++q._ended;
20949     q._tasks[i] = null;
20950     if (q._error != null) return; // ignore secondary errors
20951     if (e != null) {
20952       abort(q, e);
20953     } else {
20954       q._data[i] = r;
20955       if (q._waiting) poke(q);
20956       else maybeNotify(q);
20957     }
20958   };
20959 }
20960
20961 function abort(q, e) {
20962   var i = q._tasks.length, t;
20963   q._error = e; // ignore active callbacks
20964   q._data = undefined; // allow gc
20965   q._waiting = NaN; // prevent starting
20966
20967   while (--i >= 0) {
20968     if (t = q._tasks[i]) {
20969       q._tasks[i] = null;
20970       if (t.abort) {
20971         try { t.abort(); }
20972         catch (e) { /* ignore */ }
20973       }
20974     }
20975   }
20976
20977   q._active = NaN; // allow notification
20978   maybeNotify(q);
20979 }
20980
20981 function maybeNotify(q) {
20982   if (!q._active && q._call) {
20983     var d = q._data;
20984     q._data = undefined; // allow gc
20985     q._call(q._error, d);
20986   }
20987 }
20988
20989 function queue(concurrency) {
20990   return new Queue(arguments.length ? +concurrency : Infinity);
20991 }
20992
20993 var constant$2 = function(x) {
20994   return function constant() {
20995     return x;
20996   };
20997 };
20998
20999 var epsilon$1 = 1e-12;
21000 var pi$2 = Math.PI;
21001 var halfPi$1 = pi$2 / 2;
21002 var tau$2 = 2 * pi$2;
21003
21004 function arcInnerRadius(d) {
21005   return d.innerRadius;
21006 }
21007
21008 function arcOuterRadius(d) {
21009   return d.outerRadius;
21010 }
21011
21012 function arcStartAngle(d) {
21013   return d.startAngle;
21014 }
21015
21016 function arcEndAngle(d) {
21017   return d.endAngle;
21018 }
21019
21020 function arcPadAngle(d) {
21021   return d && d.padAngle; // Note: optional!
21022 }
21023
21024 function asin(x) {
21025   return x >= 1 ? halfPi$1 : x <= -1 ? -halfPi$1 : Math.asin(x);
21026 }
21027
21028 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
21029   var x10 = x1 - x0, y10 = y1 - y0,
21030       x32 = x3 - x2, y32 = y3 - y2,
21031       t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
21032   return [x0 + t * x10, y0 + t * y10];
21033 }
21034
21035 // Compute perpendicular offset line of length rc.
21036 // http://mathworld.wolfram.com/Circle-LineIntersection.html
21037 function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
21038   var x01 = x0 - x1,
21039       y01 = y0 - y1,
21040       lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01),
21041       ox = lo * y01,
21042       oy = -lo * x01,
21043       x11 = x0 + ox,
21044       y11 = y0 + oy,
21045       x10 = x1 + ox,
21046       y10 = y1 + oy,
21047       x00 = (x11 + x10) / 2,
21048       y00 = (y11 + y10) / 2,
21049       dx = x10 - x11,
21050       dy = y10 - y11,
21051       d2 = dx * dx + dy * dy,
21052       r = r1 - rc,
21053       D = x11 * y10 - x10 * y11,
21054       d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)),
21055       cx0 = (D * dy - dx * d) / d2,
21056       cy0 = (-D * dx - dy * d) / d2,
21057       cx1 = (D * dy + dx * d) / d2,
21058       cy1 = (-D * dx + dy * d) / d2,
21059       dx0 = cx0 - x00,
21060       dy0 = cy0 - y00,
21061       dx1 = cx1 - x00,
21062       dy1 = cy1 - y00;
21063
21064   // Pick the closer of the two intersection points.
21065   // TODO Is there a faster way to determine which intersection to use?
21066   if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
21067
21068   return {
21069     cx: cx0,
21070     cy: cy0,
21071     x01: -ox,
21072     y01: -oy,
21073     x11: cx0 * (r1 / r - 1),
21074     y11: cy0 * (r1 / r - 1)
21075   };
21076 }
21077
21078 var arc = function() {
21079   var innerRadius = arcInnerRadius,
21080       outerRadius = arcOuterRadius,
21081       cornerRadius = constant$2(0),
21082       padRadius = null,
21083       startAngle = arcStartAngle,
21084       endAngle = arcEndAngle,
21085       padAngle = arcPadAngle,
21086       context = null;
21087
21088   function arc() {
21089     var buffer,
21090         r,
21091         r0 = +innerRadius.apply(this, arguments),
21092         r1 = +outerRadius.apply(this, arguments),
21093         a0 = startAngle.apply(this, arguments) - halfPi$1,
21094         a1 = endAngle.apply(this, arguments) - halfPi$1,
21095         da = Math.abs(a1 - a0),
21096         cw = a1 > a0;
21097
21098     if (!context) context = buffer = path();
21099
21100     // Ensure that the outer radius is always larger than the inner radius.
21101     if (r1 < r0) r = r1, r1 = r0, r0 = r;
21102
21103     // Is it a point?
21104     if (!(r1 > epsilon$1)) context.moveTo(0, 0);
21105
21106     // Or is it a circle or annulus?
21107     else if (da > tau$2 - epsilon$1) {
21108       context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0));
21109       context.arc(0, 0, r1, a0, a1, !cw);
21110       if (r0 > epsilon$1) {
21111         context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1));
21112         context.arc(0, 0, r0, a1, a0, cw);
21113       }
21114     }
21115
21116     // Or is it a circular or annular sector?
21117     else {
21118       var a01 = a0,
21119           a11 = a1,
21120           a00 = a0,
21121           a10 = a1,
21122           da0 = da,
21123           da1 = da,
21124           ap = padAngle.apply(this, arguments) / 2,
21125           rp = (ap > epsilon$1) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)),
21126           rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
21127           rc0 = rc,
21128           rc1 = rc,
21129           t0,
21130           t1;
21131
21132       // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
21133       if (rp > epsilon$1) {
21134         var p0 = asin(rp / r0 * Math.sin(ap)),
21135             p1 = asin(rp / r1 * Math.sin(ap));
21136         if ((da0 -= p0 * 2) > epsilon$1) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
21137         else da0 = 0, a00 = a10 = (a0 + a1) / 2;
21138         if ((da1 -= p1 * 2) > epsilon$1) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
21139         else da1 = 0, a01 = a11 = (a0 + a1) / 2;
21140       }
21141
21142       var x01 = r1 * Math.cos(a01),
21143           y01 = r1 * Math.sin(a01),
21144           x10 = r0 * Math.cos(a10),
21145           y10 = r0 * Math.sin(a10);
21146
21147       // Apply rounded corners?
21148       if (rc > epsilon$1) {
21149         var x11 = r1 * Math.cos(a11),
21150             y11 = r1 * Math.sin(a11),
21151             x00 = r0 * Math.cos(a00),
21152             y00 = r0 * Math.sin(a00);
21153
21154         // Restrict the corner radius according to the sector angle.
21155         if (da < pi$2) {
21156           var oc = da0 > epsilon$1 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
21157               ax = x01 - oc[0],
21158               ay = y01 - oc[1],
21159               bx = x11 - oc[0],
21160               by = y11 - oc[1],
21161               kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2),
21162               lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
21163           rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
21164           rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
21165         }
21166       }
21167
21168       // Is the sector collapsed to a line?
21169       if (!(da1 > epsilon$1)) context.moveTo(x01, y01);
21170
21171       // Does the sector’s outer ring have rounded corners?
21172       else if (rc1 > epsilon$1) {
21173         t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
21174         t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
21175
21176         context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
21177
21178         // Have the corners merged?
21179         if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
21180
21181         // Otherwise, draw the two corners and the ring.
21182         else {
21183           context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
21184           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);
21185           context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
21186         }
21187       }
21188
21189       // Or is the outer ring just a circular arc?
21190       else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
21191
21192       // Is there no inner ring, and it’s a circular sector?
21193       // Or perhaps it’s an annular sector collapsed due to padding?
21194       if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10);
21195
21196       // Does the sector’s inner ring (or point) have rounded corners?
21197       else if (rc0 > epsilon$1) {
21198         t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
21199         t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
21200
21201         context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
21202
21203         // Have the corners merged?
21204         if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
21205
21206         // Otherwise, draw the two corners and the ring.
21207         else {
21208           context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
21209           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);
21210           context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
21211         }
21212       }
21213
21214       // Or is the inner ring just a circular arc?
21215       else context.arc(0, 0, r0, a10, a00, cw);
21216     }
21217
21218     context.closePath();
21219
21220     if (buffer) return context = null, buffer + "" || null;
21221   }
21222
21223   arc.centroid = function() {
21224     var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
21225         a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$2 / 2;
21226     return [Math.cos(a) * r, Math.sin(a) * r];
21227   };
21228
21229   arc.innerRadius = function(_) {
21230     return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : innerRadius;
21231   };
21232
21233   arc.outerRadius = function(_) {
21234     return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : outerRadius;
21235   };
21236
21237   arc.cornerRadius = function(_) {
21238     return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : cornerRadius;
21239   };
21240
21241   arc.padRadius = function(_) {
21242     return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), arc) : padRadius;
21243   };
21244
21245   arc.startAngle = function(_) {
21246     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : startAngle;
21247   };
21248
21249   arc.endAngle = function(_) {
21250     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : endAngle;
21251   };
21252
21253   arc.padAngle = function(_) {
21254     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : padAngle;
21255   };
21256
21257   arc.context = function(_) {
21258     return arguments.length ? ((context = _ == null ? null : _), arc) : context;
21259   };
21260
21261   return arc;
21262 };
21263
21264 function Linear(context) {
21265   this._context = context;
21266 }
21267
21268 Linear.prototype = {
21269   areaStart: function() {
21270     this._line = 0;
21271   },
21272   areaEnd: function() {
21273     this._line = NaN;
21274   },
21275   lineStart: function() {
21276     this._point = 0;
21277   },
21278   lineEnd: function() {
21279     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21280     this._line = 1 - this._line;
21281   },
21282   point: function(x, y) {
21283     x = +x, y = +y;
21284     switch (this._point) {
21285       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21286       case 1: this._point = 2; // proceed
21287       default: this._context.lineTo(x, y); break;
21288     }
21289   }
21290 };
21291
21292 var curveLinear = function(context) {
21293   return new Linear(context);
21294 };
21295
21296 function x(p) {
21297   return p[0];
21298 }
21299
21300 function y(p) {
21301   return p[1];
21302 }
21303
21304 var line = function() {
21305   var x$$1 = x,
21306       y$$1 = y,
21307       defined = constant$2(true),
21308       context = null,
21309       curve = curveLinear,
21310       output = null;
21311
21312   function line(data) {
21313     var i,
21314         n = data.length,
21315         d,
21316         defined0 = false,
21317         buffer;
21318
21319     if (context == null) output = curve(buffer = path());
21320
21321     for (i = 0; i <= n; ++i) {
21322       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
21323         if (defined0 = !defined0) output.lineStart();
21324         else output.lineEnd();
21325       }
21326       if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data));
21327     }
21328
21329     if (buffer) return output = null, buffer + "" || null;
21330   }
21331
21332   line.x = function(_) {
21333     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : x$$1;
21334   };
21335
21336   line.y = function(_) {
21337     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : y$$1;
21338   };
21339
21340   line.defined = function(_) {
21341     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), line) : defined;
21342   };
21343
21344   line.curve = function(_) {
21345     return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
21346   };
21347
21348   line.context = function(_) {
21349     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
21350   };
21351
21352   return line;
21353 };
21354
21355 var area = function() {
21356   var x0 = x,
21357       x1 = null,
21358       y0 = constant$2(0),
21359       y1 = y,
21360       defined = constant$2(true),
21361       context = null,
21362       curve = curveLinear,
21363       output = null;
21364
21365   function area(data) {
21366     var i,
21367         j,
21368         k,
21369         n = data.length,
21370         d,
21371         defined0 = false,
21372         buffer,
21373         x0z = new Array(n),
21374         y0z = new Array(n);
21375
21376     if (context == null) output = curve(buffer = path());
21377
21378     for (i = 0; i <= n; ++i) {
21379       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
21380         if (defined0 = !defined0) {
21381           j = i;
21382           output.areaStart();
21383           output.lineStart();
21384         } else {
21385           output.lineEnd();
21386           output.lineStart();
21387           for (k = i - 1; k >= j; --k) {
21388             output.point(x0z[k], y0z[k]);
21389           }
21390           output.lineEnd();
21391           output.areaEnd();
21392         }
21393       }
21394       if (defined0) {
21395         x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
21396         output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
21397       }
21398     }
21399
21400     if (buffer) return output = null, buffer + "" || null;
21401   }
21402
21403   function arealine() {
21404     return line().defined(defined).curve(curve).context(context);
21405   }
21406
21407   area.x = function(_) {
21408     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), x1 = null, area) : x0;
21409   };
21410
21411   area.x0 = function(_) {
21412     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), area) : x0;
21413   };
21414
21415   area.x1 = function(_) {
21416     return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : x1;
21417   };
21418
21419   area.y = function(_) {
21420     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), y1 = null, area) : y0;
21421   };
21422
21423   area.y0 = function(_) {
21424     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), area) : y0;
21425   };
21426
21427   area.y1 = function(_) {
21428     return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : y1;
21429   };
21430
21431   area.lineX0 =
21432   area.lineY0 = function() {
21433     return arealine().x(x0).y(y0);
21434   };
21435
21436   area.lineY1 = function() {
21437     return arealine().x(x0).y(y1);
21438   };
21439
21440   area.lineX1 = function() {
21441     return arealine().x(x1).y(y0);
21442   };
21443
21444   area.defined = function(_) {
21445     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), area) : defined;
21446   };
21447
21448   area.curve = function(_) {
21449     return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
21450   };
21451
21452   area.context = function(_) {
21453     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
21454   };
21455
21456   return area;
21457 };
21458
21459 var descending$1 = function(a, b) {
21460   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
21461 };
21462
21463 var identity$1 = function(d) {
21464   return d;
21465 };
21466
21467 var pie = function() {
21468   var value = identity$1,
21469       sortValues = descending$1,
21470       sort = null,
21471       startAngle = constant$2(0),
21472       endAngle = constant$2(tau$2),
21473       padAngle = constant$2(0);
21474
21475   function pie(data) {
21476     var i,
21477         n = data.length,
21478         j,
21479         k,
21480         sum = 0,
21481         index = new Array(n),
21482         arcs = new Array(n),
21483         a0 = +startAngle.apply(this, arguments),
21484         da = Math.min(tau$2, Math.max(-tau$2, endAngle.apply(this, arguments) - a0)),
21485         a1,
21486         p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
21487         pa = p * (da < 0 ? -1 : 1),
21488         v;
21489
21490     for (i = 0; i < n; ++i) {
21491       if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
21492         sum += v;
21493       }
21494     }
21495
21496     // Optionally sort the arcs by previously-computed values or by data.
21497     if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
21498     else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });
21499
21500     // Compute the arcs! They are stored in the original data's order.
21501     for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
21502       j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
21503         data: data[j],
21504         index: i,
21505         value: v,
21506         startAngle: a0,
21507         endAngle: a1,
21508         padAngle: p
21509       };
21510     }
21511
21512     return arcs;
21513   }
21514
21515   pie.value = function(_) {
21516     return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), pie) : value;
21517   };
21518
21519   pie.sortValues = function(_) {
21520     return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
21521   };
21522
21523   pie.sort = function(_) {
21524     return arguments.length ? (sort = _, sortValues = null, pie) : sort;
21525   };
21526
21527   pie.startAngle = function(_) {
21528     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : startAngle;
21529   };
21530
21531   pie.endAngle = function(_) {
21532     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : endAngle;
21533   };
21534
21535   pie.padAngle = function(_) {
21536     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : padAngle;
21537   };
21538
21539   return pie;
21540 };
21541
21542 var curveRadialLinear = curveRadial(curveLinear);
21543
21544 function Radial(curve) {
21545   this._curve = curve;
21546 }
21547
21548 Radial.prototype = {
21549   areaStart: function() {
21550     this._curve.areaStart();
21551   },
21552   areaEnd: function() {
21553     this._curve.areaEnd();
21554   },
21555   lineStart: function() {
21556     this._curve.lineStart();
21557   },
21558   lineEnd: function() {
21559     this._curve.lineEnd();
21560   },
21561   point: function(a, r) {
21562     this._curve.point(r * Math.sin(a), r * -Math.cos(a));
21563   }
21564 };
21565
21566 function curveRadial(curve) {
21567
21568   function radial(context) {
21569     return new Radial(curve(context));
21570   }
21571
21572   radial._curve = curve;
21573
21574   return radial;
21575 }
21576
21577 function radialLine(l) {
21578   var c = l.curve;
21579
21580   l.angle = l.x, delete l.x;
21581   l.radius = l.y, delete l.y;
21582
21583   l.curve = function(_) {
21584     return arguments.length ? c(curveRadial(_)) : c()._curve;
21585   };
21586
21587   return l;
21588 }
21589
21590 var radialLine$1 = function() {
21591   return radialLine(line().curve(curveRadialLinear));
21592 };
21593
21594 var radialArea = function() {
21595   var a = area().curve(curveRadialLinear),
21596       c = a.curve,
21597       x0 = a.lineX0,
21598       x1 = a.lineX1,
21599       y0 = a.lineY0,
21600       y1 = a.lineY1;
21601
21602   a.angle = a.x, delete a.x;
21603   a.startAngle = a.x0, delete a.x0;
21604   a.endAngle = a.x1, delete a.x1;
21605   a.radius = a.y, delete a.y;
21606   a.innerRadius = a.y0, delete a.y0;
21607   a.outerRadius = a.y1, delete a.y1;
21608   a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0;
21609   a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1;
21610   a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0;
21611   a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1;
21612
21613   a.curve = function(_) {
21614     return arguments.length ? c(curveRadial(_)) : c()._curve;
21615   };
21616
21617   return a;
21618 };
21619
21620 var circle = {
21621   draw: function(context, size) {
21622     var r = Math.sqrt(size / pi$2);
21623     context.moveTo(r, 0);
21624     context.arc(0, 0, r, 0, tau$2);
21625   }
21626 };
21627
21628 var cross$1 = {
21629   draw: function(context, size) {
21630     var r = Math.sqrt(size / 5) / 2;
21631     context.moveTo(-3 * r, -r);
21632     context.lineTo(-r, -r);
21633     context.lineTo(-r, -3 * r);
21634     context.lineTo(r, -3 * r);
21635     context.lineTo(r, -r);
21636     context.lineTo(3 * r, -r);
21637     context.lineTo(3 * r, r);
21638     context.lineTo(r, r);
21639     context.lineTo(r, 3 * r);
21640     context.lineTo(-r, 3 * r);
21641     context.lineTo(-r, r);
21642     context.lineTo(-3 * r, r);
21643     context.closePath();
21644   }
21645 };
21646
21647 var tan30 = Math.sqrt(1 / 3);
21648 var tan30_2 = tan30 * 2;
21649
21650 var diamond = {
21651   draw: function(context, size) {
21652     var y = Math.sqrt(size / tan30_2),
21653         x = y * tan30;
21654     context.moveTo(0, -y);
21655     context.lineTo(x, 0);
21656     context.lineTo(0, y);
21657     context.lineTo(-x, 0);
21658     context.closePath();
21659   }
21660 };
21661
21662 var ka = 0.89081309152928522810;
21663 var kr = Math.sin(pi$2 / 10) / Math.sin(7 * pi$2 / 10);
21664 var kx = Math.sin(tau$2 / 10) * kr;
21665 var ky = -Math.cos(tau$2 / 10) * kr;
21666
21667 var star = {
21668   draw: function(context, size) {
21669     var r = Math.sqrt(size * ka),
21670         x = kx * r,
21671         y = ky * r;
21672     context.moveTo(0, -r);
21673     context.lineTo(x, y);
21674     for (var i = 1; i < 5; ++i) {
21675       var a = tau$2 * i / 5,
21676           c = Math.cos(a),
21677           s = Math.sin(a);
21678       context.lineTo(s * r, -c * r);
21679       context.lineTo(c * x - s * y, s * x + c * y);
21680     }
21681     context.closePath();
21682   }
21683 };
21684
21685 var square = {
21686   draw: function(context, size) {
21687     var w = Math.sqrt(size),
21688         x = -w / 2;
21689     context.rect(x, x, w, w);
21690   }
21691 };
21692
21693 var sqrt3 = Math.sqrt(3);
21694
21695 var triangle = {
21696   draw: function(context, size) {
21697     var y = -Math.sqrt(size / (sqrt3 * 3));
21698     context.moveTo(0, y * 2);
21699     context.lineTo(-sqrt3 * y, -y);
21700     context.lineTo(sqrt3 * y, -y);
21701     context.closePath();
21702   }
21703 };
21704
21705 var c = -0.5;
21706 var s = Math.sqrt(3) / 2;
21707 var k = 1 / Math.sqrt(12);
21708 var a = (k / 2 + 1) * 3;
21709
21710 var wye = {
21711   draw: function(context, size) {
21712     var r = Math.sqrt(size / a),
21713         x0 = r / 2,
21714         y0 = r * k,
21715         x1 = x0,
21716         y1 = r * k + r,
21717         x2 = -x1,
21718         y2 = y1;
21719     context.moveTo(x0, y0);
21720     context.lineTo(x1, y1);
21721     context.lineTo(x2, y2);
21722     context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
21723     context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
21724     context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
21725     context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
21726     context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
21727     context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
21728     context.closePath();
21729   }
21730 };
21731
21732 var symbols = [
21733   circle,
21734   cross$1,
21735   diamond,
21736   square,
21737   star,
21738   triangle,
21739   wye
21740 ];
21741
21742 var symbol = function() {
21743   var type = constant$2(circle),
21744       size = constant$2(64),
21745       context = null;
21746
21747   function symbol() {
21748     var buffer;
21749     if (!context) context = buffer = path();
21750     type.apply(this, arguments).draw(context, +size.apply(this, arguments));
21751     if (buffer) return context = null, buffer + "" || null;
21752   }
21753
21754   symbol.type = function(_) {
21755     return arguments.length ? (type = typeof _ === "function" ? _ : constant$2(_), symbol) : type;
21756   };
21757
21758   symbol.size = function(_) {
21759     return arguments.length ? (size = typeof _ === "function" ? _ : constant$2(+_), symbol) : size;
21760   };
21761
21762   symbol.context = function(_) {
21763     return arguments.length ? (context = _ == null ? null : _, symbol) : context;
21764   };
21765
21766   return symbol;
21767 };
21768
21769 var noop = function() {};
21770
21771 function point(that, x, y) {
21772   that._context.bezierCurveTo(
21773     (2 * that._x0 + that._x1) / 3,
21774     (2 * that._y0 + that._y1) / 3,
21775     (that._x0 + 2 * that._x1) / 3,
21776     (that._y0 + 2 * that._y1) / 3,
21777     (that._x0 + 4 * that._x1 + x) / 6,
21778     (that._y0 + 4 * that._y1 + y) / 6
21779   );
21780 }
21781
21782 function Basis(context) {
21783   this._context = context;
21784 }
21785
21786 Basis.prototype = {
21787   areaStart: function() {
21788     this._line = 0;
21789   },
21790   areaEnd: function() {
21791     this._line = NaN;
21792   },
21793   lineStart: function() {
21794     this._x0 = this._x1 =
21795     this._y0 = this._y1 = NaN;
21796     this._point = 0;
21797   },
21798   lineEnd: function() {
21799     switch (this._point) {
21800       case 3: point(this, this._x1, this._y1); // proceed
21801       case 2: this._context.lineTo(this._x1, this._y1); break;
21802     }
21803     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21804     this._line = 1 - this._line;
21805   },
21806   point: function(x, y) {
21807     x = +x, y = +y;
21808     switch (this._point) {
21809       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21810       case 1: this._point = 2; break;
21811       case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
21812       default: point(this, x, y); break;
21813     }
21814     this._x0 = this._x1, this._x1 = x;
21815     this._y0 = this._y1, this._y1 = y;
21816   }
21817 };
21818
21819 var basis = function(context) {
21820   return new Basis(context);
21821 };
21822
21823 function BasisClosed(context) {
21824   this._context = context;
21825 }
21826
21827 BasisClosed.prototype = {
21828   areaStart: noop,
21829   areaEnd: noop,
21830   lineStart: function() {
21831     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
21832     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
21833     this._point = 0;
21834   },
21835   lineEnd: function() {
21836     switch (this._point) {
21837       case 1: {
21838         this._context.moveTo(this._x2, this._y2);
21839         this._context.closePath();
21840         break;
21841       }
21842       case 2: {
21843         this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
21844         this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
21845         this._context.closePath();
21846         break;
21847       }
21848       case 3: {
21849         this.point(this._x2, this._y2);
21850         this.point(this._x3, this._y3);
21851         this.point(this._x4, this._y4);
21852         break;
21853       }
21854     }
21855   },
21856   point: function(x, y) {
21857     x = +x, y = +y;
21858     switch (this._point) {
21859       case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
21860       case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
21861       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;
21862       default: point(this, x, y); break;
21863     }
21864     this._x0 = this._x1, this._x1 = x;
21865     this._y0 = this._y1, this._y1 = y;
21866   }
21867 };
21868
21869 var basisClosed = function(context) {
21870   return new BasisClosed(context);
21871 };
21872
21873 function BasisOpen(context) {
21874   this._context = context;
21875 }
21876
21877 BasisOpen.prototype = {
21878   areaStart: function() {
21879     this._line = 0;
21880   },
21881   areaEnd: function() {
21882     this._line = NaN;
21883   },
21884   lineStart: function() {
21885     this._x0 = this._x1 =
21886     this._y0 = this._y1 = NaN;
21887     this._point = 0;
21888   },
21889   lineEnd: function() {
21890     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
21891     this._line = 1 - this._line;
21892   },
21893   point: function(x, y) {
21894     x = +x, y = +y;
21895     switch (this._point) {
21896       case 0: this._point = 1; break;
21897       case 1: this._point = 2; break;
21898       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;
21899       case 3: this._point = 4; // proceed
21900       default: point(this, x, y); break;
21901     }
21902     this._x0 = this._x1, this._x1 = x;
21903     this._y0 = this._y1, this._y1 = y;
21904   }
21905 };
21906
21907 var basisOpen = function(context) {
21908   return new BasisOpen(context);
21909 };
21910
21911 function Bundle(context, beta) {
21912   this._basis = new Basis(context);
21913   this._beta = beta;
21914 }
21915
21916 Bundle.prototype = {
21917   lineStart: function() {
21918     this._x = [];
21919     this._y = [];
21920     this._basis.lineStart();
21921   },
21922   lineEnd: function() {
21923     var x = this._x,
21924         y = this._y,
21925         j = x.length - 1;
21926
21927     if (j > 0) {
21928       var x0 = x[0],
21929           y0 = y[0],
21930           dx = x[j] - x0,
21931           dy = y[j] - y0,
21932           i = -1,
21933           t;
21934
21935       while (++i <= j) {
21936         t = i / j;
21937         this._basis.point(
21938           this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
21939           this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
21940         );
21941       }
21942     }
21943
21944     this._x = this._y = null;
21945     this._basis.lineEnd();
21946   },
21947   point: function(x, y) {
21948     this._x.push(+x);
21949     this._y.push(+y);
21950   }
21951 };
21952
21953 var bundle = (function custom(beta) {
21954
21955   function bundle(context) {
21956     return beta === 1 ? new Basis(context) : new Bundle(context, beta);
21957   }
21958
21959   bundle.beta = function(beta) {
21960     return custom(+beta);
21961   };
21962
21963   return bundle;
21964 })(0.85);
21965
21966 function point$1(that, x, y) {
21967   that._context.bezierCurveTo(
21968     that._x1 + that._k * (that._x2 - that._x0),
21969     that._y1 + that._k * (that._y2 - that._y0),
21970     that._x2 + that._k * (that._x1 - x),
21971     that._y2 + that._k * (that._y1 - y),
21972     that._x2,
21973     that._y2
21974   );
21975 }
21976
21977 function Cardinal(context, tension) {
21978   this._context = context;
21979   this._k = (1 - tension) / 6;
21980 }
21981
21982 Cardinal.prototype = {
21983   areaStart: function() {
21984     this._line = 0;
21985   },
21986   areaEnd: function() {
21987     this._line = NaN;
21988   },
21989   lineStart: function() {
21990     this._x0 = this._x1 = this._x2 =
21991     this._y0 = this._y1 = this._y2 = NaN;
21992     this._point = 0;
21993   },
21994   lineEnd: function() {
21995     switch (this._point) {
21996       case 2: this._context.lineTo(this._x2, this._y2); break;
21997       case 3: point$1(this, this._x1, this._y1); break;
21998     }
21999     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22000     this._line = 1 - this._line;
22001   },
22002   point: function(x, y) {
22003     x = +x, y = +y;
22004     switch (this._point) {
22005       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22006       case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
22007       case 2: this._point = 3; // proceed
22008       default: point$1(this, x, y); break;
22009     }
22010     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22011     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22012   }
22013 };
22014
22015 var cardinal = (function custom(tension) {
22016
22017   function cardinal(context) {
22018     return new Cardinal(context, tension);
22019   }
22020
22021   cardinal.tension = function(tension) {
22022     return custom(+tension);
22023   };
22024
22025   return cardinal;
22026 })(0);
22027
22028 function CardinalClosed(context, tension) {
22029   this._context = context;
22030   this._k = (1 - tension) / 6;
22031 }
22032
22033 CardinalClosed.prototype = {
22034   areaStart: noop,
22035   areaEnd: noop,
22036   lineStart: function() {
22037     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
22038     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
22039     this._point = 0;
22040   },
22041   lineEnd: function() {
22042     switch (this._point) {
22043       case 1: {
22044         this._context.moveTo(this._x3, this._y3);
22045         this._context.closePath();
22046         break;
22047       }
22048       case 2: {
22049         this._context.lineTo(this._x3, this._y3);
22050         this._context.closePath();
22051         break;
22052       }
22053       case 3: {
22054         this.point(this._x3, this._y3);
22055         this.point(this._x4, this._y4);
22056         this.point(this._x5, this._y5);
22057         break;
22058       }
22059     }
22060   },
22061   point: function(x, y) {
22062     x = +x, y = +y;
22063     switch (this._point) {
22064       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
22065       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
22066       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
22067       default: point$1(this, x, y); break;
22068     }
22069     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22070     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22071   }
22072 };
22073
22074 var cardinalClosed = (function custom(tension) {
22075
22076   function cardinal(context) {
22077     return new CardinalClosed(context, tension);
22078   }
22079
22080   cardinal.tension = function(tension) {
22081     return custom(+tension);
22082   };
22083
22084   return cardinal;
22085 })(0);
22086
22087 function CardinalOpen(context, tension) {
22088   this._context = context;
22089   this._k = (1 - tension) / 6;
22090 }
22091
22092 CardinalOpen.prototype = {
22093   areaStart: function() {
22094     this._line = 0;
22095   },
22096   areaEnd: function() {
22097     this._line = NaN;
22098   },
22099   lineStart: function() {
22100     this._x0 = this._x1 = this._x2 =
22101     this._y0 = this._y1 = this._y2 = NaN;
22102     this._point = 0;
22103   },
22104   lineEnd: function() {
22105     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
22106     this._line = 1 - this._line;
22107   },
22108   point: function(x, y) {
22109     x = +x, y = +y;
22110     switch (this._point) {
22111       case 0: this._point = 1; break;
22112       case 1: this._point = 2; break;
22113       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
22114       case 3: this._point = 4; // proceed
22115       default: point$1(this, x, y); break;
22116     }
22117     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22118     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22119   }
22120 };
22121
22122 var cardinalOpen = (function custom(tension) {
22123
22124   function cardinal(context) {
22125     return new CardinalOpen(context, tension);
22126   }
22127
22128   cardinal.tension = function(tension) {
22129     return custom(+tension);
22130   };
22131
22132   return cardinal;
22133 })(0);
22134
22135 function point$2(that, x, y) {
22136   var x1 = that._x1,
22137       y1 = that._y1,
22138       x2 = that._x2,
22139       y2 = that._y2;
22140
22141   if (that._l01_a > epsilon$1) {
22142     var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
22143         n = 3 * that._l01_a * (that._l01_a + that._l12_a);
22144     x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
22145     y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
22146   }
22147
22148   if (that._l23_a > epsilon$1) {
22149     var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
22150         m = 3 * that._l23_a * (that._l23_a + that._l12_a);
22151     x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
22152     y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
22153   }
22154
22155   that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
22156 }
22157
22158 function CatmullRom(context, alpha) {
22159   this._context = context;
22160   this._alpha = alpha;
22161 }
22162
22163 CatmullRom.prototype = {
22164   areaStart: function() {
22165     this._line = 0;
22166   },
22167   areaEnd: function() {
22168     this._line = NaN;
22169   },
22170   lineStart: function() {
22171     this._x0 = this._x1 = this._x2 =
22172     this._y0 = this._y1 = this._y2 = NaN;
22173     this._l01_a = this._l12_a = this._l23_a =
22174     this._l01_2a = this._l12_2a = this._l23_2a =
22175     this._point = 0;
22176   },
22177   lineEnd: function() {
22178     switch (this._point) {
22179       case 2: this._context.lineTo(this._x2, this._y2); break;
22180       case 3: this.point(this._x2, this._y2); break;
22181     }
22182     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22183     this._line = 1 - this._line;
22184   },
22185   point: function(x, y) {
22186     x = +x, y = +y;
22187
22188     if (this._point) {
22189       var x23 = this._x2 - x,
22190           y23 = this._y2 - y;
22191       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22192     }
22193
22194     switch (this._point) {
22195       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22196       case 1: this._point = 2; break;
22197       case 2: this._point = 3; // proceed
22198       default: point$2(this, x, y); break;
22199     }
22200
22201     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22202     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22203     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22204     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22205   }
22206 };
22207
22208 var catmullRom = (function custom(alpha) {
22209
22210   function catmullRom(context) {
22211     return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
22212   }
22213
22214   catmullRom.alpha = function(alpha) {
22215     return custom(+alpha);
22216   };
22217
22218   return catmullRom;
22219 })(0.5);
22220
22221 function CatmullRomClosed(context, alpha) {
22222   this._context = context;
22223   this._alpha = alpha;
22224 }
22225
22226 CatmullRomClosed.prototype = {
22227   areaStart: noop,
22228   areaEnd: noop,
22229   lineStart: function() {
22230     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
22231     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
22232     this._l01_a = this._l12_a = this._l23_a =
22233     this._l01_2a = this._l12_2a = this._l23_2a =
22234     this._point = 0;
22235   },
22236   lineEnd: function() {
22237     switch (this._point) {
22238       case 1: {
22239         this._context.moveTo(this._x3, this._y3);
22240         this._context.closePath();
22241         break;
22242       }
22243       case 2: {
22244         this._context.lineTo(this._x3, this._y3);
22245         this._context.closePath();
22246         break;
22247       }
22248       case 3: {
22249         this.point(this._x3, this._y3);
22250         this.point(this._x4, this._y4);
22251         this.point(this._x5, this._y5);
22252         break;
22253       }
22254     }
22255   },
22256   point: function(x, y) {
22257     x = +x, y = +y;
22258
22259     if (this._point) {
22260       var x23 = this._x2 - x,
22261           y23 = this._y2 - y;
22262       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22263     }
22264
22265     switch (this._point) {
22266       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
22267       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
22268       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
22269       default: point$2(this, x, y); break;
22270     }
22271
22272     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22273     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22274     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22275     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22276   }
22277 };
22278
22279 var catmullRomClosed = (function custom(alpha) {
22280
22281   function catmullRom(context) {
22282     return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
22283   }
22284
22285   catmullRom.alpha = function(alpha) {
22286     return custom(+alpha);
22287   };
22288
22289   return catmullRom;
22290 })(0.5);
22291
22292 function CatmullRomOpen(context, alpha) {
22293   this._context = context;
22294   this._alpha = alpha;
22295 }
22296
22297 CatmullRomOpen.prototype = {
22298   areaStart: function() {
22299     this._line = 0;
22300   },
22301   areaEnd: function() {
22302     this._line = NaN;
22303   },
22304   lineStart: function() {
22305     this._x0 = this._x1 = this._x2 =
22306     this._y0 = this._y1 = this._y2 = NaN;
22307     this._l01_a = this._l12_a = this._l23_a =
22308     this._l01_2a = this._l12_2a = this._l23_2a =
22309     this._point = 0;
22310   },
22311   lineEnd: function() {
22312     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
22313     this._line = 1 - this._line;
22314   },
22315   point: function(x, y) {
22316     x = +x, y = +y;
22317
22318     if (this._point) {
22319       var x23 = this._x2 - x,
22320           y23 = this._y2 - y;
22321       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22322     }
22323
22324     switch (this._point) {
22325       case 0: this._point = 1; break;
22326       case 1: this._point = 2; break;
22327       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
22328       case 3: this._point = 4; // proceed
22329       default: point$2(this, x, y); break;
22330     }
22331
22332     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22333     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22334     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22335     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22336   }
22337 };
22338
22339 var catmullRomOpen = (function custom(alpha) {
22340
22341   function catmullRom(context) {
22342     return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
22343   }
22344
22345   catmullRom.alpha = function(alpha) {
22346     return custom(+alpha);
22347   };
22348
22349   return catmullRom;
22350 })(0.5);
22351
22352 function LinearClosed(context) {
22353   this._context = context;
22354 }
22355
22356 LinearClosed.prototype = {
22357   areaStart: noop,
22358   areaEnd: noop,
22359   lineStart: function() {
22360     this._point = 0;
22361   },
22362   lineEnd: function() {
22363     if (this._point) this._context.closePath();
22364   },
22365   point: function(x, y) {
22366     x = +x, y = +y;
22367     if (this._point) this._context.lineTo(x, y);
22368     else this._point = 1, this._context.moveTo(x, y);
22369   }
22370 };
22371
22372 var linearClosed = function(context) {
22373   return new LinearClosed(context);
22374 };
22375
22376 function sign(x) {
22377   return x < 0 ? -1 : 1;
22378 }
22379
22380 // Calculate the slopes of the tangents (Hermite-type interpolation) based on
22381 // the following paper: Steffen, M. 1990. A Simple Method for Monotonic
22382 // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
22383 // NOV(II), P. 443, 1990.
22384 function slope3(that, x2, y2) {
22385   var h0 = that._x1 - that._x0,
22386       h1 = x2 - that._x1,
22387       s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
22388       s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
22389       p = (s0 * h1 + s1 * h0) / (h0 + h1);
22390   return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
22391 }
22392
22393 // Calculate a one-sided slope.
22394 function slope2(that, t) {
22395   var h = that._x1 - that._x0;
22396   return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
22397 }
22398
22399 // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
22400 // "you can express cubic Hermite interpolation in terms of cubic Bézier curves
22401 // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
22402 function point$3(that, t0, t1) {
22403   var x0 = that._x0,
22404       y0 = that._y0,
22405       x1 = that._x1,
22406       y1 = that._y1,
22407       dx = (x1 - x0) / 3;
22408   that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
22409 }
22410
22411 function MonotoneX(context) {
22412   this._context = context;
22413 }
22414
22415 MonotoneX.prototype = {
22416   areaStart: function() {
22417     this._line = 0;
22418   },
22419   areaEnd: function() {
22420     this._line = NaN;
22421   },
22422   lineStart: function() {
22423     this._x0 = this._x1 =
22424     this._y0 = this._y1 =
22425     this._t0 = NaN;
22426     this._point = 0;
22427   },
22428   lineEnd: function() {
22429     switch (this._point) {
22430       case 2: this._context.lineTo(this._x1, this._y1); break;
22431       case 3: point$3(this, this._t0, slope2(this, this._t0)); break;
22432     }
22433     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22434     this._line = 1 - this._line;
22435   },
22436   point: function(x, y) {
22437     var t1 = NaN;
22438
22439     x = +x, y = +y;
22440     if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
22441     switch (this._point) {
22442       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22443       case 1: this._point = 2; break;
22444       case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
22445       default: point$3(this, this._t0, t1 = slope3(this, x, y)); break;
22446     }
22447
22448     this._x0 = this._x1, this._x1 = x;
22449     this._y0 = this._y1, this._y1 = y;
22450     this._t0 = t1;
22451   }
22452 };
22453
22454 function MonotoneY(context) {
22455   this._context = new ReflectContext(context);
22456 }
22457
22458 (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
22459   MonotoneX.prototype.point.call(this, y, x);
22460 };
22461
22462 function ReflectContext(context) {
22463   this._context = context;
22464 }
22465
22466 ReflectContext.prototype = {
22467   moveTo: function(x, y) { this._context.moveTo(y, x); },
22468   closePath: function() { this._context.closePath(); },
22469   lineTo: function(x, y) { this._context.lineTo(y, x); },
22470   bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
22471 };
22472
22473 function monotoneX(context) {
22474   return new MonotoneX(context);
22475 }
22476
22477 function monotoneY(context) {
22478   return new MonotoneY(context);
22479 }
22480
22481 function Natural(context) {
22482   this._context = context;
22483 }
22484
22485 Natural.prototype = {
22486   areaStart: function() {
22487     this._line = 0;
22488   },
22489   areaEnd: function() {
22490     this._line = NaN;
22491   },
22492   lineStart: function() {
22493     this._x = [];
22494     this._y = [];
22495   },
22496   lineEnd: function() {
22497     var x = this._x,
22498         y = this._y,
22499         n = x.length;
22500
22501     if (n) {
22502       this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
22503       if (n === 2) {
22504         this._context.lineTo(x[1], y[1]);
22505       } else {
22506         var px = controlPoints(x),
22507             py = controlPoints(y);
22508         for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
22509           this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
22510         }
22511       }
22512     }
22513
22514     if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
22515     this._line = 1 - this._line;
22516     this._x = this._y = null;
22517   },
22518   point: function(x, y) {
22519     this._x.push(+x);
22520     this._y.push(+y);
22521   }
22522 };
22523
22524 // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
22525 function controlPoints(x) {
22526   var i,
22527       n = x.length - 1,
22528       m,
22529       a = new Array(n),
22530       b = new Array(n),
22531       r = new Array(n);
22532   a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
22533   for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
22534   a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
22535   for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
22536   a[n - 1] = r[n - 1] / b[n - 1];
22537   for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
22538   b[n - 1] = (x[n] + a[n - 1]) / 2;
22539   for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
22540   return [a, b];
22541 }
22542
22543 var natural = function(context) {
22544   return new Natural(context);
22545 };
22546
22547 function Step(context, t) {
22548   this._context = context;
22549   this._t = t;
22550 }
22551
22552 Step.prototype = {
22553   areaStart: function() {
22554     this._line = 0;
22555   },
22556   areaEnd: function() {
22557     this._line = NaN;
22558   },
22559   lineStart: function() {
22560     this._x = this._y = NaN;
22561     this._point = 0;
22562   },
22563   lineEnd: function() {
22564     if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
22565     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22566     if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
22567   },
22568   point: function(x, y) {
22569     x = +x, y = +y;
22570     switch (this._point) {
22571       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22572       case 1: this._point = 2; // proceed
22573       default: {
22574         if (this._t <= 0) {
22575           this._context.lineTo(this._x, y);
22576           this._context.lineTo(x, y);
22577         } else {
22578           var x1 = this._x * (1 - this._t) + x * this._t;
22579           this._context.lineTo(x1, this._y);
22580           this._context.lineTo(x1, y);
22581         }
22582         break;
22583       }
22584     }
22585     this._x = x, this._y = y;
22586   }
22587 };
22588
22589 var step = function(context) {
22590   return new Step(context, 0.5);
22591 };
22592
22593 function stepBefore(context) {
22594   return new Step(context, 0);
22595 }
22596
22597 function stepAfter(context) {
22598   return new Step(context, 1);
22599 }
22600
22601 var slice$2 = Array.prototype.slice;
22602
22603 var none = function(series, order) {
22604   if (!((n = series.length) > 1)) return;
22605   for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
22606     s0 = s1, s1 = series[order[i]];
22607     for (var j = 0; j < m; ++j) {
22608       s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
22609     }
22610   }
22611 };
22612
22613 var none$1 = function(series) {
22614   var n = series.length, o = new Array(n);
22615   while (--n >= 0) o[n] = n;
22616   return o;
22617 };
22618
22619 function stackValue(d, key) {
22620   return d[key];
22621 }
22622
22623 var stack = function() {
22624   var keys = constant$2([]),
22625       order = none$1,
22626       offset = none,
22627       value = stackValue;
22628
22629   function stack(data) {
22630     var kz = keys.apply(this, arguments),
22631         i,
22632         m = data.length,
22633         n = kz.length,
22634         sz = new Array(n),
22635         oz;
22636
22637     for (i = 0; i < n; ++i) {
22638       for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
22639         si[j] = sij = [0, +value(data[j], ki, j, data)];
22640         sij.data = data[j];
22641       }
22642       si.key = ki;
22643     }
22644
22645     for (i = 0, oz = order(sz); i < n; ++i) {
22646       sz[oz[i]].index = i;
22647     }
22648
22649     offset(sz, oz);
22650     return sz;
22651   }
22652
22653   stack.keys = function(_) {
22654     return arguments.length ? (keys = typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : keys;
22655   };
22656
22657   stack.value = function(_) {
22658     return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), stack) : value;
22659   };
22660
22661   stack.order = function(_) {
22662     return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : order;
22663   };
22664
22665   stack.offset = function(_) {
22666     return arguments.length ? (offset = _ == null ? none : _, stack) : offset;
22667   };
22668
22669   return stack;
22670 };
22671
22672 var expand = function(series, order) {
22673   if (!((n = series.length) > 0)) return;
22674   for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
22675     for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
22676     if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
22677   }
22678   none(series, order);
22679 };
22680
22681 var silhouette = function(series, order) {
22682   if (!((n = series.length) > 0)) return;
22683   for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
22684     for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
22685     s0[j][1] += s0[j][0] = -y / 2;
22686   }
22687   none(series, order);
22688 };
22689
22690 var wiggle = function(series, order) {
22691   if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
22692   for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
22693     for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
22694       var si = series[order[i]],
22695           sij0 = si[j][1] || 0,
22696           sij1 = si[j - 1][1] || 0,
22697           s3 = (sij0 - sij1) / 2;
22698       for (var k = 0; k < i; ++k) {
22699         var sk = series[order[k]],
22700             skj0 = sk[j][1] || 0,
22701             skj1 = sk[j - 1][1] || 0;
22702         s3 += skj0 - skj1;
22703       }
22704       s1 += sij0, s2 += s3 * sij0;
22705     }
22706     s0[j - 1][1] += s0[j - 1][0] = y;
22707     if (s1) y -= s2 / s1;
22708   }
22709   s0[j - 1][1] += s0[j - 1][0] = y;
22710   none(series, order);
22711 };
22712
22713 var ascending$1 = function(series) {
22714   var sums = series.map(sum$1);
22715   return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; });
22716 };
22717
22718 function sum$1(series) {
22719   var s = 0, i = -1, n = series.length, v;
22720   while (++i < n) if (v = +series[i][1]) s += v;
22721   return s;
22722 }
22723
22724 var descending$2 = function(series) {
22725   return ascending$1(series).reverse();
22726 };
22727
22728 var insideOut = function(series) {
22729   var n = series.length,
22730       i,
22731       j,
22732       sums = series.map(sum$1),
22733       order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }),
22734       top = 0,
22735       bottom = 0,
22736       tops = [],
22737       bottoms = [];
22738
22739   for (i = 0; i < n; ++i) {
22740     j = order[i];
22741     if (top < bottom) {
22742       top += sums[j];
22743       tops.push(j);
22744     } else {
22745       bottom += sums[j];
22746       bottoms.push(j);
22747     }
22748   }
22749
22750   return bottoms.reverse().concat(tops);
22751 };
22752
22753 var reverse = function(series) {
22754   return none$1(series).reverse();
22755 };
22756
22757 var define$1 = function(constructor, factory, prototype) {
22758   constructor.prototype = factory.prototype = prototype;
22759   prototype.constructor = constructor;
22760 };
22761
22762 function extend(parent, definition) {
22763   var prototype = Object.create(parent.prototype);
22764   for (var key in definition) prototype[key] = definition[key];
22765   return prototype;
22766 }
22767
22768 function Color() {}
22769
22770 var darker = 0.7;
22771 var brighter = 1 / darker;
22772
22773 var reHex3 = /^#([0-9a-f]{3})$/;
22774 var reHex6 = /^#([0-9a-f]{6})$/;
22775 var reRgbInteger = /^rgb\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*\)$/;
22776 var reRgbPercent = /^rgb\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
22777 var reRgbaInteger = /^rgba\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
22778 var reRgbaPercent = /^rgba\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
22779 var reHslPercent = /^hsl\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
22780 var reHslaPercent = /^hsla\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
22781
22782 var named = {
22783   aliceblue: 0xf0f8ff,
22784   antiquewhite: 0xfaebd7,
22785   aqua: 0x00ffff,
22786   aquamarine: 0x7fffd4,
22787   azure: 0xf0ffff,
22788   beige: 0xf5f5dc,
22789   bisque: 0xffe4c4,
22790   black: 0x000000,
22791   blanchedalmond: 0xffebcd,
22792   blue: 0x0000ff,
22793   blueviolet: 0x8a2be2,
22794   brown: 0xa52a2a,
22795   burlywood: 0xdeb887,
22796   cadetblue: 0x5f9ea0,
22797   chartreuse: 0x7fff00,
22798   chocolate: 0xd2691e,
22799   coral: 0xff7f50,
22800   cornflowerblue: 0x6495ed,
22801   cornsilk: 0xfff8dc,
22802   crimson: 0xdc143c,
22803   cyan: 0x00ffff,
22804   darkblue: 0x00008b,
22805   darkcyan: 0x008b8b,
22806   darkgoldenrod: 0xb8860b,
22807   darkgray: 0xa9a9a9,
22808   darkgreen: 0x006400,
22809   darkgrey: 0xa9a9a9,
22810   darkkhaki: 0xbdb76b,
22811   darkmagenta: 0x8b008b,
22812   darkolivegreen: 0x556b2f,
22813   darkorange: 0xff8c00,
22814   darkorchid: 0x9932cc,
22815   darkred: 0x8b0000,
22816   darksalmon: 0xe9967a,
22817   darkseagreen: 0x8fbc8f,
22818   darkslateblue: 0x483d8b,
22819   darkslategray: 0x2f4f4f,
22820   darkslategrey: 0x2f4f4f,
22821   darkturquoise: 0x00ced1,
22822   darkviolet: 0x9400d3,
22823   deeppink: 0xff1493,
22824   deepskyblue: 0x00bfff,
22825   dimgray: 0x696969,
22826   dimgrey: 0x696969,
22827   dodgerblue: 0x1e90ff,
22828   firebrick: 0xb22222,
22829   floralwhite: 0xfffaf0,
22830   forestgreen: 0x228b22,
22831   fuchsia: 0xff00ff,
22832   gainsboro: 0xdcdcdc,
22833   ghostwhite: 0xf8f8ff,
22834   gold: 0xffd700,
22835   goldenrod: 0xdaa520,
22836   gray: 0x808080,
22837   green: 0x008000,
22838   greenyellow: 0xadff2f,
22839   grey: 0x808080,
22840   honeydew: 0xf0fff0,
22841   hotpink: 0xff69b4,
22842   indianred: 0xcd5c5c,
22843   indigo: 0x4b0082,
22844   ivory: 0xfffff0,
22845   khaki: 0xf0e68c,
22846   lavender: 0xe6e6fa,
22847   lavenderblush: 0xfff0f5,
22848   lawngreen: 0x7cfc00,
22849   lemonchiffon: 0xfffacd,
22850   lightblue: 0xadd8e6,
22851   lightcoral: 0xf08080,
22852   lightcyan: 0xe0ffff,
22853   lightgoldenrodyellow: 0xfafad2,
22854   lightgray: 0xd3d3d3,
22855   lightgreen: 0x90ee90,
22856   lightgrey: 0xd3d3d3,
22857   lightpink: 0xffb6c1,
22858   lightsalmon: 0xffa07a,
22859   lightseagreen: 0x20b2aa,
22860   lightskyblue: 0x87cefa,
22861   lightslategray: 0x778899,
22862   lightslategrey: 0x778899,
22863   lightsteelblue: 0xb0c4de,
22864   lightyellow: 0xffffe0,
22865   lime: 0x00ff00,
22866   limegreen: 0x32cd32,
22867   linen: 0xfaf0e6,
22868   magenta: 0xff00ff,
22869   maroon: 0x800000,
22870   mediumaquamarine: 0x66cdaa,
22871   mediumblue: 0x0000cd,
22872   mediumorchid: 0xba55d3,
22873   mediumpurple: 0x9370db,
22874   mediumseagreen: 0x3cb371,
22875   mediumslateblue: 0x7b68ee,
22876   mediumspringgreen: 0x00fa9a,
22877   mediumturquoise: 0x48d1cc,
22878   mediumvioletred: 0xc71585,
22879   midnightblue: 0x191970,
22880   mintcream: 0xf5fffa,
22881   mistyrose: 0xffe4e1,
22882   moccasin: 0xffe4b5,
22883   navajowhite: 0xffdead,
22884   navy: 0x000080,
22885   oldlace: 0xfdf5e6,
22886   olive: 0x808000,
22887   olivedrab: 0x6b8e23,
22888   orange: 0xffa500,
22889   orangered: 0xff4500,
22890   orchid: 0xda70d6,
22891   palegoldenrod: 0xeee8aa,
22892   palegreen: 0x98fb98,
22893   paleturquoise: 0xafeeee,
22894   palevioletred: 0xdb7093,
22895   papayawhip: 0xffefd5,
22896   peachpuff: 0xffdab9,
22897   peru: 0xcd853f,
22898   pink: 0xffc0cb,
22899   plum: 0xdda0dd,
22900   powderblue: 0xb0e0e6,
22901   purple: 0x800080,
22902   rebeccapurple: 0x663399,
22903   red: 0xff0000,
22904   rosybrown: 0xbc8f8f,
22905   royalblue: 0x4169e1,
22906   saddlebrown: 0x8b4513,
22907   salmon: 0xfa8072,
22908   sandybrown: 0xf4a460,
22909   seagreen: 0x2e8b57,
22910   seashell: 0xfff5ee,
22911   sienna: 0xa0522d,
22912   silver: 0xc0c0c0,
22913   skyblue: 0x87ceeb,
22914   slateblue: 0x6a5acd,
22915   slategray: 0x708090,
22916   slategrey: 0x708090,
22917   snow: 0xfffafa,
22918   springgreen: 0x00ff7f,
22919   steelblue: 0x4682b4,
22920   tan: 0xd2b48c,
22921   teal: 0x008080,
22922   thistle: 0xd8bfd8,
22923   tomato: 0xff6347,
22924   turquoise: 0x40e0d0,
22925   violet: 0xee82ee,
22926   wheat: 0xf5deb3,
22927   white: 0xffffff,
22928   whitesmoke: 0xf5f5f5,
22929   yellow: 0xffff00,
22930   yellowgreen: 0x9acd32
22931 };
22932
22933 define$1(Color, color, {
22934   displayable: function() {
22935     return this.rgb().displayable();
22936   },
22937   toString: function() {
22938     return this.rgb() + "";
22939   }
22940 });
22941
22942 function color(format) {
22943   var m;
22944   format = (format + "").trim().toLowerCase();
22945   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
22946       : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
22947       : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
22948       : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
22949       : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
22950       : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
22951       : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
22952       : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
22953       : named.hasOwnProperty(format) ? rgbn(named[format])
22954       : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
22955       : null;
22956 }
22957
22958 function rgbn(n) {
22959   return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
22960 }
22961
22962 function rgba(r, g, b, a) {
22963   if (a <= 0) r = g = b = NaN;
22964   return new Rgb(r, g, b, a);
22965 }
22966
22967 function rgbConvert(o) {
22968   if (!(o instanceof Color)) o = color(o);
22969   if (!o) return new Rgb;
22970   o = o.rgb();
22971   return new Rgb(o.r, o.g, o.b, o.opacity);
22972 }
22973
22974 function rgb(r, g, b, opacity) {
22975   return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
22976 }
22977
22978 function Rgb(r, g, b, opacity) {
22979   this.r = +r;
22980   this.g = +g;
22981   this.b = +b;
22982   this.opacity = +opacity;
22983 }
22984
22985 define$1(Rgb, rgb, extend(Color, {
22986   brighter: function(k) {
22987     k = k == null ? brighter : Math.pow(brighter, k);
22988     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
22989   },
22990   darker: function(k) {
22991     k = k == null ? darker : Math.pow(darker, k);
22992     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
22993   },
22994   rgb: function() {
22995     return this;
22996   },
22997   displayable: function() {
22998     return (0 <= this.r && this.r <= 255)
22999         && (0 <= this.g && this.g <= 255)
23000         && (0 <= this.b && this.b <= 255)
23001         && (0 <= this.opacity && this.opacity <= 1);
23002   },
23003   toString: function() {
23004     var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
23005     return (a === 1 ? "rgb(" : "rgba(")
23006         + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
23007         + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
23008         + Math.max(0, Math.min(255, Math.round(this.b) || 0))
23009         + (a === 1 ? ")" : ", " + a + ")");
23010   }
23011 }));
23012
23013 function hsla(h, s, l, a) {
23014   if (a <= 0) h = s = l = NaN;
23015   else if (l <= 0 || l >= 1) h = s = NaN;
23016   else if (s <= 0) h = NaN;
23017   return new Hsl(h, s, l, a);
23018 }
23019
23020 function hslConvert(o) {
23021   if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
23022   if (!(o instanceof Color)) o = color(o);
23023   if (!o) return new Hsl;
23024   if (o instanceof Hsl) return o;
23025   o = o.rgb();
23026   var r = o.r / 255,
23027       g = o.g / 255,
23028       b = o.b / 255,
23029       min = Math.min(r, g, b),
23030       max = Math.max(r, g, b),
23031       h = NaN,
23032       s = max - min,
23033       l = (max + min) / 2;
23034   if (s) {
23035     if (r === max) h = (g - b) / s + (g < b) * 6;
23036     else if (g === max) h = (b - r) / s + 2;
23037     else h = (r - g) / s + 4;
23038     s /= l < 0.5 ? max + min : 2 - max - min;
23039     h *= 60;
23040   } else {
23041     s = l > 0 && l < 1 ? 0 : h;
23042   }
23043   return new Hsl(h, s, l, o.opacity);
23044 }
23045
23046 function hsl(h, s, l, opacity) {
23047   return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
23048 }
23049
23050 function Hsl(h, s, l, opacity) {
23051   this.h = +h;
23052   this.s = +s;
23053   this.l = +l;
23054   this.opacity = +opacity;
23055 }
23056
23057 define$1(Hsl, hsl, extend(Color, {
23058   brighter: function(k) {
23059     k = k == null ? brighter : Math.pow(brighter, k);
23060     return new Hsl(this.h, this.s, this.l * k, this.opacity);
23061   },
23062   darker: function(k) {
23063     k = k == null ? darker : Math.pow(darker, k);
23064     return new Hsl(this.h, this.s, this.l * k, this.opacity);
23065   },
23066   rgb: function() {
23067     var h = this.h % 360 + (this.h < 0) * 360,
23068         s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
23069         l = this.l,
23070         m2 = l + (l < 0.5 ? l : 1 - l) * s,
23071         m1 = 2 * l - m2;
23072     return new Rgb(
23073       hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
23074       hsl2rgb(h, m1, m2),
23075       hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
23076       this.opacity
23077     );
23078   },
23079   displayable: function() {
23080     return (0 <= this.s && this.s <= 1 || isNaN(this.s))
23081         && (0 <= this.l && this.l <= 1)
23082         && (0 <= this.opacity && this.opacity <= 1);
23083   }
23084 }));
23085
23086 /* From FvD 13.37, CSS Color Module Level 3 */
23087 function hsl2rgb(h, m1, m2) {
23088   return (h < 60 ? m1 + (m2 - m1) * h / 60
23089       : h < 180 ? m2
23090       : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
23091       : m1) * 255;
23092 }
23093
23094 var deg2rad = Math.PI / 180;
23095 var rad2deg = 180 / Math.PI;
23096
23097 var Kn = 18;
23098 var Xn = 0.950470;
23099 var Yn = 1;
23100 var Zn = 1.088830;
23101 var t0 = 4 / 29;
23102 var t1 = 6 / 29;
23103 var t2 = 3 * t1 * t1;
23104 var t3 = t1 * t1 * t1;
23105
23106 function labConvert(o) {
23107   if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
23108   if (o instanceof Hcl) {
23109     var h = o.h * deg2rad;
23110     return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
23111   }
23112   if (!(o instanceof Rgb)) o = rgbConvert(o);
23113   var b = rgb2xyz(o.r),
23114       a = rgb2xyz(o.g),
23115       l = rgb2xyz(o.b),
23116       x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
23117       y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
23118       z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
23119   return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
23120 }
23121
23122 function lab(l, a, b, opacity) {
23123   return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
23124 }
23125
23126 function Lab(l, a, b, opacity) {
23127   this.l = +l;
23128   this.a = +a;
23129   this.b = +b;
23130   this.opacity = +opacity;
23131 }
23132
23133 define$1(Lab, lab, extend(Color, {
23134   brighter: function(k) {
23135     return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
23136   },
23137   darker: function(k) {
23138     return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
23139   },
23140   rgb: function() {
23141     var y = (this.l + 16) / 116,
23142         x = isNaN(this.a) ? y : y + this.a / 500,
23143         z = isNaN(this.b) ? y : y - this.b / 200;
23144     y = Yn * lab2xyz(y);
23145     x = Xn * lab2xyz(x);
23146     z = Zn * lab2xyz(z);
23147     return new Rgb(
23148       xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
23149       xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
23150       xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
23151       this.opacity
23152     );
23153   }
23154 }));
23155
23156 function xyz2lab(t) {
23157   return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
23158 }
23159
23160 function lab2xyz(t) {
23161   return t > t1 ? t * t * t : t2 * (t - t0);
23162 }
23163
23164 function xyz2rgb(x) {
23165   return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
23166 }
23167
23168 function rgb2xyz(x) {
23169   return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
23170 }
23171
23172 function hclConvert(o) {
23173   if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
23174   if (!(o instanceof Lab)) o = labConvert(o);
23175   var h = Math.atan2(o.b, o.a) * rad2deg;
23176   return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
23177 }
23178
23179 function hcl(h, c, l, opacity) {
23180   return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
23181 }
23182
23183 function Hcl(h, c, l, opacity) {
23184   this.h = +h;
23185   this.c = +c;
23186   this.l = +l;
23187   this.opacity = +opacity;
23188 }
23189
23190 define$1(Hcl, hcl, extend(Color, {
23191   brighter: function(k) {
23192     return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
23193   },
23194   darker: function(k) {
23195     return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
23196   },
23197   rgb: function() {
23198     return labConvert(this).rgb();
23199   }
23200 }));
23201
23202 var A = -0.14861;
23203 var B = +1.78277;
23204 var C = -0.29227;
23205 var D = -0.90649;
23206 var E = +1.97294;
23207 var ED = E * D;
23208 var EB = E * B;
23209 var BC_DA = B * C - D * A;
23210
23211 function cubehelixConvert(o) {
23212   if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
23213   if (!(o instanceof Rgb)) o = rgbConvert(o);
23214   var r = o.r / 255,
23215       g = o.g / 255,
23216       b = o.b / 255,
23217       l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
23218       bl = b - l,
23219       k = (E * (g - l) - C * bl) / D,
23220       s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
23221       h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
23222   return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
23223 }
23224
23225 function cubehelix(h, s, l, opacity) {
23226   return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
23227 }
23228
23229 function Cubehelix(h, s, l, opacity) {
23230   this.h = +h;
23231   this.s = +s;
23232   this.l = +l;
23233   this.opacity = +opacity;
23234 }
23235
23236 define$1(Cubehelix, cubehelix, extend(Color, {
23237   brighter: function(k) {
23238     k = k == null ? brighter : Math.pow(brighter, k);
23239     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
23240   },
23241   darker: function(k) {
23242     k = k == null ? darker : Math.pow(darker, k);
23243     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
23244   },
23245   rgb: function() {
23246     var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
23247         l = +this.l,
23248         a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
23249         cosh = Math.cos(h),
23250         sinh = Math.sin(h);
23251     return new Rgb(
23252       255 * (l + a * (A * cosh + B * sinh)),
23253       255 * (l + a * (C * cosh + D * sinh)),
23254       255 * (l + a * (E * cosh)),
23255       this.opacity
23256     );
23257   }
23258 }));
23259
23260 function basis$1(t1, v0, v1, v2, v3) {
23261   var t2 = t1 * t1, t3 = t2 * t1;
23262   return ((1 - 3 * t1 + 3 * t2 - t3) * v0
23263       + (4 - 6 * t2 + 3 * t3) * v1
23264       + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
23265       + t3 * v3) / 6;
23266 }
23267
23268 var basis$2 = function(values) {
23269   var n = values.length - 1;
23270   return function(t) {
23271     var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
23272         v1 = values[i],
23273         v2 = values[i + 1],
23274         v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
23275         v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
23276     return basis$1((t - i / n) * n, v0, v1, v2, v3);
23277   };
23278 };
23279
23280 var basisClosed$1 = function(values) {
23281   var n = values.length;
23282   return function(t) {
23283     var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
23284         v0 = values[(i + n - 1) % n],
23285         v1 = values[i % n],
23286         v2 = values[(i + 1) % n],
23287         v3 = values[(i + 2) % n];
23288     return basis$1((t - i / n) * n, v0, v1, v2, v3);
23289   };
23290 };
23291
23292 var constant$3 = function(x) {
23293   return function() {
23294     return x;
23295   };
23296 };
23297
23298 function linear$1(a, d) {
23299   return function(t) {
23300     return a + t * d;
23301   };
23302 }
23303
23304 function exponential$1(a, b, y) {
23305   return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
23306     return Math.pow(a + t * b, y);
23307   };
23308 }
23309
23310 function hue(a, b) {
23311   var d = b - a;
23312   return d ? linear$1(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
23313 }
23314
23315 function gamma(y) {
23316   return (y = +y) === 1 ? nogamma : function(a, b) {
23317     return b - a ? exponential$1(a, b, y) : constant$3(isNaN(a) ? b : a);
23318   };
23319 }
23320
23321 function nogamma(a, b) {
23322   var d = b - a;
23323   return d ? linear$1(a, d) : constant$3(isNaN(a) ? b : a);
23324 }
23325
23326 var interpolateRgb = (function rgbGamma(y) {
23327   var color$$1 = gamma(y);
23328
23329   function rgb$$1(start, end) {
23330     var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
23331         g = color$$1(start.g, end.g),
23332         b = color$$1(start.b, end.b),
23333         opacity = color$$1(start.opacity, end.opacity);
23334     return function(t) {
23335       start.r = r(t);
23336       start.g = g(t);
23337       start.b = b(t);
23338       start.opacity = opacity(t);
23339       return start + "";
23340     };
23341   }
23342
23343   rgb$$1.gamma = rgbGamma;
23344
23345   return rgb$$1;
23346 })(1);
23347
23348 function rgbSpline(spline) {
23349   return function(colors) {
23350     var n = colors.length,
23351         r = new Array(n),
23352         g = new Array(n),
23353         b = new Array(n),
23354         i, color$$1;
23355     for (i = 0; i < n; ++i) {
23356       color$$1 = rgb(colors[i]);
23357       r[i] = color$$1.r || 0;
23358       g[i] = color$$1.g || 0;
23359       b[i] = color$$1.b || 0;
23360     }
23361     r = spline(r);
23362     g = spline(g);
23363     b = spline(b);
23364     color$$1.opacity = 1;
23365     return function(t) {
23366       color$$1.r = r(t);
23367       color$$1.g = g(t);
23368       color$$1.b = b(t);
23369       return color$$1 + "";
23370     };
23371   };
23372 }
23373
23374 var rgbBasis = rgbSpline(basis$2);
23375 var rgbBasisClosed = rgbSpline(basisClosed$1);
23376
23377 var array$1 = function(a, b) {
23378   var nb = b ? b.length : 0,
23379       na = a ? Math.min(nb, a.length) : 0,
23380       x = new Array(nb),
23381       c = new Array(nb),
23382       i;
23383
23384   for (i = 0; i < na; ++i) x[i] = interpolate(a[i], b[i]);
23385   for (; i < nb; ++i) c[i] = b[i];
23386
23387   return function(t) {
23388     for (i = 0; i < na; ++i) c[i] = x[i](t);
23389     return c;
23390   };
23391 };
23392
23393 var date = function(a, b) {
23394   var d = new Date;
23395   return a = +a, b -= a, function(t) {
23396     return d.setTime(a + b * t), d;
23397   };
23398 };
23399
23400 var interpolateNumber = function(a, b) {
23401   return a = +a, b -= a, function(t) {
23402     return a + b * t;
23403   };
23404 };
23405
23406 var object = function(a, b) {
23407   var i = {},
23408       c = {},
23409       k;
23410
23411   if (a === null || typeof a !== "object") a = {};
23412   if (b === null || typeof b !== "object") b = {};
23413
23414   for (k in b) {
23415     if (k in a) {
23416       i[k] = interpolate(a[k], b[k]);
23417     } else {
23418       c[k] = b[k];
23419     }
23420   }
23421
23422   return function(t) {
23423     for (k in i) c[k] = i[k](t);
23424     return c;
23425   };
23426 };
23427
23428 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
23429 var reB = new RegExp(reA.source, "g");
23430
23431 function zero(b) {
23432   return function() {
23433     return b;
23434   };
23435 }
23436
23437 function one(b) {
23438   return function(t) {
23439     return b(t) + "";
23440   };
23441 }
23442
23443 var interpolateString = function(a, b) {
23444   var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
23445       am, // current match in a
23446       bm, // current match in b
23447       bs, // string preceding current number in b, if any
23448       i = -1, // index in s
23449       s = [], // string constants and placeholders
23450       q = []; // number interpolators
23451
23452   // Coerce inputs to strings.
23453   a = a + "", b = b + "";
23454
23455   // Interpolate pairs of numbers in a & b.
23456   while ((am = reA.exec(a))
23457       && (bm = reB.exec(b))) {
23458     if ((bs = bm.index) > bi) { // a string precedes the next number in b
23459       bs = b.slice(bi, bs);
23460       if (s[i]) s[i] += bs; // coalesce with previous string
23461       else s[++i] = bs;
23462     }
23463     if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
23464       if (s[i]) s[i] += bm; // coalesce with previous string
23465       else s[++i] = bm;
23466     } else { // interpolate non-matching numbers
23467       s[++i] = null;
23468       q.push({i: i, x: interpolateNumber(am, bm)});
23469     }
23470     bi = reB.lastIndex;
23471   }
23472
23473   // Add remains of b.
23474   if (bi < b.length) {
23475     bs = b.slice(bi);
23476     if (s[i]) s[i] += bs; // coalesce with previous string
23477     else s[++i] = bs;
23478   }
23479
23480   // Special optimization for only a single match.
23481   // Otherwise, interpolate each of the numbers and rejoin the string.
23482   return s.length < 2 ? (q[0]
23483       ? one(q[0].x)
23484       : zero(b))
23485       : (b = q.length, function(t) {
23486           for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
23487           return s.join("");
23488         });
23489 };
23490
23491 var interpolate = function(a, b) {
23492   var t = typeof b, c;
23493   return b == null || t === "boolean" ? constant$3(b)
23494       : (t === "number" ? interpolateNumber
23495       : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString)
23496       : b instanceof color ? interpolateRgb
23497       : b instanceof Date ? date
23498       : Array.isArray(b) ? array$1
23499       : isNaN(b) ? object
23500       : interpolateNumber)(a, b);
23501 };
23502
23503 var interpolateRound = function(a, b) {
23504   return a = +a, b -= a, function(t) {
23505     return Math.round(a + b * t);
23506   };
23507 };
23508
23509 var degrees = 180 / Math.PI;
23510
23511 var identity$2 = {
23512   translateX: 0,
23513   translateY: 0,
23514   rotate: 0,
23515   skewX: 0,
23516   scaleX: 1,
23517   scaleY: 1
23518 };
23519
23520 var decompose = function(a, b, c, d, e, f) {
23521   var scaleX, scaleY, skewX;
23522   if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
23523   if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
23524   if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
23525   if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
23526   return {
23527     translateX: e,
23528     translateY: f,
23529     rotate: Math.atan2(b, a) * degrees,
23530     skewX: Math.atan(skewX) * degrees,
23531     scaleX: scaleX,
23532     scaleY: scaleY
23533   };
23534 };
23535
23536 var cssNode;
23537 var cssRoot;
23538 var cssView;
23539 var svgNode;
23540
23541 function parseCss(value) {
23542   if (value === "none") return identity$2;
23543   if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
23544   cssNode.style.transform = value;
23545   value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
23546   cssRoot.removeChild(cssNode);
23547   value = value.slice(7, -1).split(",");
23548   return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
23549 }
23550
23551 function parseSvg(value) {
23552   if (value == null) return identity$2;
23553   if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
23554   svgNode.setAttribute("transform", value);
23555   if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2;
23556   value = value.matrix;
23557   return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
23558 }
23559
23560 function interpolateTransform(parse, pxComma, pxParen, degParen) {
23561
23562   function pop(s) {
23563     return s.length ? s.pop() + " " : "";
23564   }
23565
23566   function translate(xa, ya, xb, yb, s, q) {
23567     if (xa !== xb || ya !== yb) {
23568       var i = s.push("translate(", null, pxComma, null, pxParen);
23569       q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)});
23570     } else if (xb || yb) {
23571       s.push("translate(" + xb + pxComma + yb + pxParen);
23572     }
23573   }
23574
23575   function rotate(a, b, s, q) {
23576     if (a !== b) {
23577       if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
23578       q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)});
23579     } else if (b) {
23580       s.push(pop(s) + "rotate(" + b + degParen);
23581     }
23582   }
23583
23584   function skewX(a, b, s, q) {
23585     if (a !== b) {
23586       q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)});
23587     } else if (b) {
23588       s.push(pop(s) + "skewX(" + b + degParen);
23589     }
23590   }
23591
23592   function scale(xa, ya, xb, yb, s, q) {
23593     if (xa !== xb || ya !== yb) {
23594       var i = s.push(pop(s) + "scale(", null, ",", null, ")");
23595       q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)});
23596     } else if (xb !== 1 || yb !== 1) {
23597       s.push(pop(s) + "scale(" + xb + "," + yb + ")");
23598     }
23599   }
23600
23601   return function(a, b) {
23602     var s = [], // string constants and placeholders
23603         q = []; // number interpolators
23604     a = parse(a), b = parse(b);
23605     translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
23606     rotate(a.rotate, b.rotate, s, q);
23607     skewX(a.skewX, b.skewX, s, q);
23608     scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
23609     a = b = null; // gc
23610     return function(t) {
23611       var i = -1, n = q.length, o;
23612       while (++i < n) s[(o = q[i]).i] = o.x(t);
23613       return s.join("");
23614     };
23615   };
23616 }
23617
23618 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
23619 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
23620
23621 var rho = Math.SQRT2;
23622 var rho2 = 2;
23623 var rho4 = 4;
23624 var epsilon2 = 1e-12;
23625
23626 function cosh(x) {
23627   return ((x = Math.exp(x)) + 1 / x) / 2;
23628 }
23629
23630 function sinh(x) {
23631   return ((x = Math.exp(x)) - 1 / x) / 2;
23632 }
23633
23634 function tanh(x) {
23635   return ((x = Math.exp(2 * x)) - 1) / (x + 1);
23636 }
23637
23638 // p0 = [ux0, uy0, w0]
23639 // p1 = [ux1, uy1, w1]
23640 var interpolateZoom = function(p0, p1) {
23641   var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
23642       ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
23643       dx = ux1 - ux0,
23644       dy = uy1 - uy0,
23645       d2 = dx * dx + dy * dy,
23646       i,
23647       S;
23648
23649   // Special case for u0 ≅ u1.
23650   if (d2 < epsilon2) {
23651     S = Math.log(w1 / w0) / rho;
23652     i = function(t) {
23653       return [
23654         ux0 + t * dx,
23655         uy0 + t * dy,
23656         w0 * Math.exp(rho * t * S)
23657       ];
23658     };
23659   }
23660
23661   // General case.
23662   else {
23663     var d1 = Math.sqrt(d2),
23664         b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
23665         b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
23666         r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
23667         r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
23668     S = (r1 - r0) / rho;
23669     i = function(t) {
23670       var s = t * S,
23671           coshr0 = cosh(r0),
23672           u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
23673       return [
23674         ux0 + u * dx,
23675         uy0 + u * dy,
23676         w0 * coshr0 / cosh(rho * s + r0)
23677       ];
23678     };
23679   }
23680
23681   i.duration = S * 1000;
23682
23683   return i;
23684 };
23685
23686 function hsl$1(hue$$1) {
23687   return function(start, end) {
23688     var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h),
23689         s = nogamma(start.s, end.s),
23690         l = nogamma(start.l, end.l),
23691         opacity = nogamma(start.opacity, end.opacity);
23692     return function(t) {
23693       start.h = h(t);
23694       start.s = s(t);
23695       start.l = l(t);
23696       start.opacity = opacity(t);
23697       return start + "";
23698     };
23699   }
23700 }
23701
23702 var hsl$2 = hsl$1(hue);
23703 var hslLong = hsl$1(nogamma);
23704
23705 function lab$1(start, end) {
23706   var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
23707       a = nogamma(start.a, end.a),
23708       b = nogamma(start.b, end.b),
23709       opacity = nogamma(start.opacity, end.opacity);
23710   return function(t) {
23711     start.l = l(t);
23712     start.a = a(t);
23713     start.b = b(t);
23714     start.opacity = opacity(t);
23715     return start + "";
23716   };
23717 }
23718
23719 function hcl$1(hue$$1) {
23720   return function(start, end) {
23721     var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h),
23722         c = nogamma(start.c, end.c),
23723         l = nogamma(start.l, end.l),
23724         opacity = nogamma(start.opacity, end.opacity);
23725     return function(t) {
23726       start.h = h(t);
23727       start.c = c(t);
23728       start.l = l(t);
23729       start.opacity = opacity(t);
23730       return start + "";
23731     };
23732   }
23733 }
23734
23735 var hcl$2 = hcl$1(hue);
23736 var hclLong = hcl$1(nogamma);
23737
23738 function cubehelix$1(hue$$1) {
23739   return (function cubehelixGamma(y) {
23740     y = +y;
23741
23742     function cubehelix$$1(start, end) {
23743       var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
23744           s = nogamma(start.s, end.s),
23745           l = nogamma(start.l, end.l),
23746           opacity = nogamma(start.opacity, end.opacity);
23747       return function(t) {
23748         start.h = h(t);
23749         start.s = s(t);
23750         start.l = l(Math.pow(t, y));
23751         start.opacity = opacity(t);
23752         return start + "";
23753       };
23754     }
23755
23756     cubehelix$$1.gamma = cubehelixGamma;
23757
23758     return cubehelix$$1;
23759   })(1);
23760 }
23761
23762 var cubehelix$2 = cubehelix$1(hue);
23763 var cubehelixLong = cubehelix$1(nogamma);
23764
23765 var quantize = function(interpolator, n) {
23766   var samples = new Array(n);
23767   for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
23768   return samples;
23769 };
23770
23771 var noop$1 = {value: function() {}};
23772
23773 function dispatch() {
23774   for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
23775     if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
23776     _[t] = [];
23777   }
23778   return new Dispatch(_);
23779 }
23780
23781 function Dispatch(_) {
23782   this._ = _;
23783 }
23784
23785 function parseTypenames(typenames, types) {
23786   return typenames.trim().split(/^|\s+/).map(function(t) {
23787     var name = "", i = t.indexOf(".");
23788     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
23789     if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
23790     return {type: t, name: name};
23791   });
23792 }
23793
23794 Dispatch.prototype = dispatch.prototype = {
23795   constructor: Dispatch,
23796   on: function(typename, callback) {
23797     var _ = this._,
23798         T = parseTypenames(typename + "", _),
23799         t,
23800         i = -1,
23801         n = T.length;
23802
23803     // If no callback was specified, return the callback of the given type and name.
23804     if (arguments.length < 2) {
23805       while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
23806       return;
23807     }
23808
23809     // If a type was specified, set the callback for the given type and name.
23810     // Otherwise, if a null callback was specified, remove callbacks of the given name.
23811     if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
23812     while (++i < n) {
23813       if (t = (typename = T[i]).type) _[t] = set$2(_[t], typename.name, callback);
23814       else if (callback == null) for (t in _) _[t] = set$2(_[t], typename.name, null);
23815     }
23816
23817     return this;
23818   },
23819   copy: function() {
23820     var copy = {}, _ = this._;
23821     for (var t in _) copy[t] = _[t].slice();
23822     return new Dispatch(copy);
23823   },
23824   call: function(type, that) {
23825     if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
23826     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
23827     for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
23828   },
23829   apply: function(type, that, args) {
23830     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
23831     for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
23832   }
23833 };
23834
23835 function get(type, name) {
23836   for (var i = 0, n = type.length, c; i < n; ++i) {
23837     if ((c = type[i]).name === name) {
23838       return c.value;
23839     }
23840   }
23841 }
23842
23843 function set$2(type, name, callback) {
23844   for (var i = 0, n = type.length; i < n; ++i) {
23845     if (type[i].name === name) {
23846       type[i] = noop$1, type = type.slice(0, i).concat(type.slice(i + 1));
23847       break;
23848     }
23849   }
23850   if (callback != null) type.push({name: name, value: callback});
23851   return type;
23852 }
23853
23854 function objectConverter(columns) {
23855   return new Function("d", "return {" + columns.map(function(name, i) {
23856     return JSON.stringify(name) + ": d[" + i + "]";
23857   }).join(",") + "}");
23858 }
23859
23860 function customConverter(columns, f) {
23861   var object = objectConverter(columns);
23862   return function(row, i) {
23863     return f(object(row), i, columns);
23864   };
23865 }
23866
23867 // Compute unique columns in order of discovery.
23868 function inferColumns(rows) {
23869   var columnSet = Object.create(null),
23870       columns = [];
23871
23872   rows.forEach(function(row) {
23873     for (var column in row) {
23874       if (!(column in columnSet)) {
23875         columns.push(columnSet[column] = column);
23876       }
23877     }
23878   });
23879
23880   return columns;
23881 }
23882
23883 var dsv = function(delimiter) {
23884   var reFormat = new RegExp("[\"" + delimiter + "\n]"),
23885       delimiterCode = delimiter.charCodeAt(0);
23886
23887   function parse(text, f) {
23888     var convert, columns, rows = parseRows(text, function(row, i) {
23889       if (convert) return convert(row, i - 1);
23890       columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
23891     });
23892     rows.columns = columns;
23893     return rows;
23894   }
23895
23896   function parseRows(text, f) {
23897     var EOL = {}, // sentinel value for end-of-line
23898         EOF = {}, // sentinel value for end-of-file
23899         rows = [], // output rows
23900         N = text.length,
23901         I = 0, // current character index
23902         n = 0, // the current line number
23903         t, // the current token
23904         eol; // is the current token followed by EOL?
23905
23906     function token() {
23907       if (I >= N) return EOF; // special case: end of file
23908       if (eol) return eol = false, EOL; // special case: end of line
23909
23910       // special case: quotes
23911       var j = I, c;
23912       if (text.charCodeAt(j) === 34) {
23913         var i = j;
23914         while (i++ < N) {
23915           if (text.charCodeAt(i) === 34) {
23916             if (text.charCodeAt(i + 1) !== 34) break;
23917             ++i;
23918           }
23919         }
23920         I = i + 2;
23921         c = text.charCodeAt(i + 1);
23922         if (c === 13) {
23923           eol = true;
23924           if (text.charCodeAt(i + 2) === 10) ++I;
23925         } else if (c === 10) {
23926           eol = true;
23927         }
23928         return text.slice(j + 1, i).replace(/""/g, "\"");
23929       }
23930
23931       // common case: find next delimiter or newline
23932       while (I < N) {
23933         var k = 1;
23934         c = text.charCodeAt(I++);
23935         if (c === 10) eol = true; // \n
23936         else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
23937         else if (c !== delimiterCode) continue;
23938         return text.slice(j, I - k);
23939       }
23940
23941       // special case: last token before EOF
23942       return text.slice(j);
23943     }
23944
23945     while ((t = token()) !== EOF) {
23946       var a = [];
23947       while (t !== EOL && t !== EOF) {
23948         a.push(t);
23949         t = token();
23950       }
23951       if (f && (a = f(a, n++)) == null) continue;
23952       rows.push(a);
23953     }
23954
23955     return rows;
23956   }
23957
23958   function format(rows, columns) {
23959     if (columns == null) columns = inferColumns(rows);
23960     return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
23961       return columns.map(function(column) {
23962         return formatValue(row[column]);
23963       }).join(delimiter);
23964     })).join("\n");
23965   }
23966
23967   function formatRows(rows) {
23968     return rows.map(formatRow).join("\n");
23969   }
23970
23971   function formatRow(row) {
23972     return row.map(formatValue).join(delimiter);
23973   }
23974
23975   function formatValue(text) {
23976     return text == null ? ""
23977         : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
23978         : text;
23979   }
23980
23981   return {
23982     parse: parse,
23983     parseRows: parseRows,
23984     format: format,
23985     formatRows: formatRows
23986   };
23987 };
23988
23989 var csv = dsv(",");
23990
23991 var csvParse = csv.parse;
23992 var csvParseRows = csv.parseRows;
23993 var csvFormat = csv.format;
23994 var csvFormatRows = csv.formatRows;
23995
23996 var tsv = dsv("\t");
23997
23998 var tsvParse = tsv.parse;
23999 var tsvParseRows = tsv.parseRows;
24000 var tsvFormat = tsv.format;
24001 var tsvFormatRows = tsv.formatRows;
24002
24003 var request = function(url, callback) {
24004   var request,
24005       event = dispatch("beforesend", "progress", "load", "error"),
24006       mimeType,
24007       headers = map$1(),
24008       xhr = new XMLHttpRequest,
24009       user = null,
24010       password = null,
24011       response,
24012       responseType,
24013       timeout = 0;
24014
24015   // If IE does not support CORS, use XDomainRequest.
24016   if (typeof XDomainRequest !== "undefined"
24017       && !("withCredentials" in xhr)
24018       && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
24019
24020   "onload" in xhr
24021       ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
24022       : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
24023
24024   function respond(o) {
24025     var status = xhr.status, result;
24026     if (!status && hasResponse(xhr)
24027         || status >= 200 && status < 300
24028         || status === 304) {
24029       if (response) {
24030         try {
24031           result = response.call(request, xhr);
24032         } catch (e) {
24033           event.call("error", request, e);
24034           return;
24035         }
24036       } else {
24037         result = xhr;
24038       }
24039       event.call("load", request, result);
24040     } else {
24041       event.call("error", request, o);
24042     }
24043   }
24044
24045   xhr.onprogress = function(e) {
24046     event.call("progress", request, e);
24047   };
24048
24049   request = {
24050     header: function(name, value) {
24051       name = (name + "").toLowerCase();
24052       if (arguments.length < 2) return headers.get(name);
24053       if (value == null) headers.remove(name);
24054       else headers.set(name, value + "");
24055       return request;
24056     },
24057
24058     // If mimeType is non-null and no Accept header is set, a default is used.
24059     mimeType: function(value) {
24060       if (!arguments.length) return mimeType;
24061       mimeType = value == null ? null : value + "";
24062       return request;
24063     },
24064
24065     // Specifies what type the response value should take;
24066     // for instance, arraybuffer, blob, document, or text.
24067     responseType: function(value) {
24068       if (!arguments.length) return responseType;
24069       responseType = value;
24070       return request;
24071     },
24072
24073     timeout: function(value) {
24074       if (!arguments.length) return timeout;
24075       timeout = +value;
24076       return request;
24077     },
24078
24079     user: function(value) {
24080       return arguments.length < 1 ? user : (user = value == null ? null : value + "", request);
24081     },
24082
24083     password: function(value) {
24084       return arguments.length < 1 ? password : (password = value == null ? null : value + "", request);
24085     },
24086
24087     // Specify how to convert the response content to a specific type;
24088     // changes the callback value on "load" events.
24089     response: function(value) {
24090       response = value;
24091       return request;
24092     },
24093
24094     // Alias for send("GET", …).
24095     get: function(data, callback) {
24096       return request.send("GET", data, callback);
24097     },
24098
24099     // Alias for send("POST", …).
24100     post: function(data, callback) {
24101       return request.send("POST", data, callback);
24102     },
24103
24104     // If callback is non-null, it will be used for error and load events.
24105     send: function(method, data, callback) {
24106       xhr.open(method, url, true, user, password);
24107       if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
24108       if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
24109       if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
24110       if (responseType != null) xhr.responseType = responseType;
24111       if (timeout > 0) xhr.timeout = timeout;
24112       if (callback == null && typeof data === "function") callback = data, data = null;
24113       if (callback != null && callback.length === 1) callback = fixCallback(callback);
24114       if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
24115       event.call("beforesend", request, xhr);
24116       xhr.send(data == null ? null : data);
24117       return request;
24118     },
24119
24120     abort: function() {
24121       xhr.abort();
24122       return request;
24123     },
24124
24125     on: function() {
24126       var value = event.on.apply(event, arguments);
24127       return value === event ? request : value;
24128     }
24129   };
24130
24131   if (callback != null) {
24132     if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
24133     return request.get(callback);
24134   }
24135
24136   return request;
24137 };
24138
24139 function fixCallback(callback) {
24140   return function(error, xhr) {
24141     callback(error == null ? xhr : null);
24142   };
24143 }
24144
24145 function hasResponse(xhr) {
24146   var type = xhr.responseType;
24147   return type && type !== "text"
24148       ? xhr.response // null on error
24149       : xhr.responseText; // "" on error
24150 }
24151
24152 var type$2 = function(defaultMimeType, response) {
24153   return function(url, callback) {
24154     var r = request(url).mimeType(defaultMimeType).response(response);
24155     if (callback != null) {
24156       if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
24157       return r.get(callback);
24158     }
24159     return r;
24160   };
24161 };
24162
24163 var html = type$2("text/html", function(xhr) {
24164   return document.createRange().createContextualFragment(xhr.responseText);
24165 });
24166
24167 var json = type$2("application/json", function(xhr) {
24168   return JSON.parse(xhr.responseText);
24169 });
24170
24171 var text = type$2("text/plain", function(xhr) {
24172   return xhr.responseText;
24173 });
24174
24175 var xml = type$2("application/xml", function(xhr) {
24176   var xml = xhr.responseXML;
24177   if (!xml) throw new Error("parse error");
24178   return xml;
24179 });
24180
24181 var dsv$1 = function(defaultMimeType, parse) {
24182   return function(url, row, callback) {
24183     if (arguments.length < 3) callback = row, row = null;
24184     var r = request(url).mimeType(defaultMimeType);
24185     r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; };
24186     r.row(row);
24187     return callback ? r.get(callback) : r;
24188   };
24189 };
24190
24191 function responseOf(parse, row) {
24192   return function(request$$1) {
24193     return parse(request$$1.responseText, row);
24194   };
24195 }
24196
24197 var csv$1 = dsv$1("text/csv", csvParse);
24198
24199 var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
24200
24201 var frame = 0;
24202 var timeout = 0;
24203 var interval = 0;
24204 var pokeDelay = 1000;
24205 var taskHead;
24206 var taskTail;
24207 var clockLast = 0;
24208 var clockNow = 0;
24209 var clockSkew = 0;
24210 var clock = typeof performance === "object" && performance.now ? performance : Date;
24211 var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
24212
24213 function now() {
24214   return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
24215 }
24216
24217 function clearNow() {
24218   clockNow = 0;
24219 }
24220
24221 function Timer() {
24222   this._call =
24223   this._time =
24224   this._next = null;
24225 }
24226
24227 Timer.prototype = timer.prototype = {
24228   constructor: Timer,
24229   restart: function(callback, delay, time) {
24230     if (typeof callback !== "function") throw new TypeError("callback is not a function");
24231     time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
24232     if (!this._next && taskTail !== this) {
24233       if (taskTail) taskTail._next = this;
24234       else taskHead = this;
24235       taskTail = this;
24236     }
24237     this._call = callback;
24238     this._time = time;
24239     sleep();
24240   },
24241   stop: function() {
24242     if (this._call) {
24243       this._call = null;
24244       this._time = Infinity;
24245       sleep();
24246     }
24247   }
24248 };
24249
24250 function timer(callback, delay, time) {
24251   var t = new Timer;
24252   t.restart(callback, delay, time);
24253   return t;
24254 }
24255
24256 function timerFlush() {
24257   now(); // Get the current time, if not already set.
24258   ++frame; // Pretend we’ve set an alarm, if we haven’t already.
24259   var t = taskHead, e;
24260   while (t) {
24261     if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
24262     t = t._next;
24263   }
24264   --frame;
24265 }
24266
24267 function wake() {
24268   clockNow = (clockLast = clock.now()) + clockSkew;
24269   frame = timeout = 0;
24270   try {
24271     timerFlush();
24272   } finally {
24273     frame = 0;
24274     nap();
24275     clockNow = 0;
24276   }
24277 }
24278
24279 function poke$1() {
24280   var now = clock.now(), delay = now - clockLast;
24281   if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
24282 }
24283
24284 function nap() {
24285   var t0, t1 = taskHead, t2, time = Infinity;
24286   while (t1) {
24287     if (t1._call) {
24288       if (time > t1._time) time = t1._time;
24289       t0 = t1, t1 = t1._next;
24290     } else {
24291       t2 = t1._next, t1._next = null;
24292       t1 = t0 ? t0._next = t2 : taskHead = t2;
24293     }
24294   }
24295   taskTail = t0;
24296   sleep(time);
24297 }
24298
24299 function sleep(time) {
24300   if (frame) return; // Soonest alarm already set, or will be.
24301   if (timeout) timeout = clearTimeout(timeout);
24302   var delay = time - clockNow;
24303   if (delay > 24) {
24304     if (time < Infinity) timeout = setTimeout(wake, delay);
24305     if (interval) interval = clearInterval(interval);
24306   } else {
24307     if (!interval) interval = setInterval(poke$1, pokeDelay);
24308     frame = 1, setFrame(wake);
24309   }
24310 }
24311
24312 var timeout$1 = function(callback, delay, time) {
24313   var t = new Timer;
24314   delay = delay == null ? 0 : +delay;
24315   t.restart(function(elapsed) {
24316     t.stop();
24317     callback(elapsed + delay);
24318   }, delay, time);
24319   return t;
24320 };
24321
24322 var interval$1 = function(callback, delay, time) {
24323   var t = new Timer, total = delay;
24324   if (delay == null) return t.restart(callback, delay, time), t;
24325   delay = +delay, time = time == null ? now() : +time;
24326   t.restart(function tick(elapsed) {
24327     elapsed += total;
24328     t.restart(tick, total += delay, time);
24329     callback(elapsed);
24330   }, delay, time);
24331   return t;
24332 };
24333
24334 var t0$1 = new Date;
24335 var t1$1 = new Date;
24336
24337 function newInterval(floori, offseti, count, field) {
24338
24339   function interval(date) {
24340     return floori(date = new Date(+date)), date;
24341   }
24342
24343   interval.floor = interval;
24344
24345   interval.ceil = function(date) {
24346     return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
24347   };
24348
24349   interval.round = function(date) {
24350     var d0 = interval(date),
24351         d1 = interval.ceil(date);
24352     return date - d0 < d1 - date ? d0 : d1;
24353   };
24354
24355   interval.offset = function(date, step) {
24356     return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
24357   };
24358
24359   interval.range = function(start, stop, step) {
24360     var range = [];
24361     start = interval.ceil(start);
24362     step = step == null ? 1 : Math.floor(step);
24363     if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
24364     do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop)
24365     return range;
24366   };
24367
24368   interval.filter = function(test) {
24369     return newInterval(function(date) {
24370       if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
24371     }, function(date, step) {
24372       if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty
24373     });
24374   };
24375
24376   if (count) {
24377     interval.count = function(start, end) {
24378       t0$1.setTime(+start), t1$1.setTime(+end);
24379       floori(t0$1), floori(t1$1);
24380       return Math.floor(count(t0$1, t1$1));
24381     };
24382
24383     interval.every = function(step) {
24384       step = Math.floor(step);
24385       return !isFinite(step) || !(step > 0) ? null
24386           : !(step > 1) ? interval
24387           : interval.filter(field
24388               ? function(d) { return field(d) % step === 0; }
24389               : function(d) { return interval.count(0, d) % step === 0; });
24390     };
24391   }
24392
24393   return interval;
24394 }
24395
24396 var millisecond = newInterval(function() {
24397   // noop
24398 }, function(date, step) {
24399   date.setTime(+date + step);
24400 }, function(start, end) {
24401   return end - start;
24402 });
24403
24404 // An optimized implementation for this simple case.
24405 millisecond.every = function(k) {
24406   k = Math.floor(k);
24407   if (!isFinite(k) || !(k > 0)) return null;
24408   if (!(k > 1)) return millisecond;
24409   return newInterval(function(date) {
24410     date.setTime(Math.floor(date / k) * k);
24411   }, function(date, step) {
24412     date.setTime(+date + step * k);
24413   }, function(start, end) {
24414     return (end - start) / k;
24415   });
24416 };
24417
24418 var milliseconds = millisecond.range;
24419
24420 var durationSecond = 1e3;
24421 var durationMinute = 6e4;
24422 var durationHour = 36e5;
24423 var durationDay = 864e5;
24424 var durationWeek = 6048e5;
24425
24426 var second = newInterval(function(date) {
24427   date.setTime(Math.floor(date / durationSecond) * durationSecond);
24428 }, function(date, step) {
24429   date.setTime(+date + step * durationSecond);
24430 }, function(start, end) {
24431   return (end - start) / durationSecond;
24432 }, function(date) {
24433   return date.getUTCSeconds();
24434 });
24435
24436 var seconds = second.range;
24437
24438 var minute = newInterval(function(date) {
24439   date.setTime(Math.floor(date / durationMinute) * durationMinute);
24440 }, function(date, step) {
24441   date.setTime(+date + step * durationMinute);
24442 }, function(start, end) {
24443   return (end - start) / durationMinute;
24444 }, function(date) {
24445   return date.getMinutes();
24446 });
24447
24448 var minutes = minute.range;
24449
24450 var hour = newInterval(function(date) {
24451   var offset = date.getTimezoneOffset() * durationMinute % durationHour;
24452   if (offset < 0) offset += durationHour;
24453   date.setTime(Math.floor((+date - offset) / durationHour) * durationHour + offset);
24454 }, function(date, step) {
24455   date.setTime(+date + step * durationHour);
24456 }, function(start, end) {
24457   return (end - start) / durationHour;
24458 }, function(date) {
24459   return date.getHours();
24460 });
24461
24462 var hours = hour.range;
24463
24464 var day = newInterval(function(date) {
24465   date.setHours(0, 0, 0, 0);
24466 }, function(date, step) {
24467   date.setDate(date.getDate() + step);
24468 }, function(start, end) {
24469   return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay;
24470 }, function(date) {
24471   return date.getDate() - 1;
24472 });
24473
24474 var days = day.range;
24475
24476 function weekday(i) {
24477   return newInterval(function(date) {
24478     date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
24479     date.setHours(0, 0, 0, 0);
24480   }, function(date, step) {
24481     date.setDate(date.getDate() + step * 7);
24482   }, function(start, end) {
24483     return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek;
24484   });
24485 }
24486
24487 var sunday = weekday(0);
24488 var monday = weekday(1);
24489 var tuesday = weekday(2);
24490 var wednesday = weekday(3);
24491 var thursday = weekday(4);
24492 var friday = weekday(5);
24493 var saturday = weekday(6);
24494
24495 var sundays = sunday.range;
24496 var mondays = monday.range;
24497 var tuesdays = tuesday.range;
24498 var wednesdays = wednesday.range;
24499 var thursdays = thursday.range;
24500 var fridays = friday.range;
24501 var saturdays = saturday.range;
24502
24503 var month = newInterval(function(date) {
24504   date.setDate(1);
24505   date.setHours(0, 0, 0, 0);
24506 }, function(date, step) {
24507   date.setMonth(date.getMonth() + step);
24508 }, function(start, end) {
24509   return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
24510 }, function(date) {
24511   return date.getMonth();
24512 });
24513
24514 var months = month.range;
24515
24516 var year = newInterval(function(date) {
24517   date.setMonth(0, 1);
24518   date.setHours(0, 0, 0, 0);
24519 }, function(date, step) {
24520   date.setFullYear(date.getFullYear() + step);
24521 }, function(start, end) {
24522   return end.getFullYear() - start.getFullYear();
24523 }, function(date) {
24524   return date.getFullYear();
24525 });
24526
24527 // An optimized implementation for this simple case.
24528 year.every = function(k) {
24529   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
24530     date.setFullYear(Math.floor(date.getFullYear() / k) * k);
24531     date.setMonth(0, 1);
24532     date.setHours(0, 0, 0, 0);
24533   }, function(date, step) {
24534     date.setFullYear(date.getFullYear() + step * k);
24535   });
24536 };
24537
24538 var years = year.range;
24539
24540 var utcMinute = newInterval(function(date) {
24541   date.setUTCSeconds(0, 0);
24542 }, function(date, step) {
24543   date.setTime(+date + step * durationMinute);
24544 }, function(start, end) {
24545   return (end - start) / durationMinute;
24546 }, function(date) {
24547   return date.getUTCMinutes();
24548 });
24549
24550 var utcMinutes = utcMinute.range;
24551
24552 var utcHour = newInterval(function(date) {
24553   date.setUTCMinutes(0, 0, 0);
24554 }, function(date, step) {
24555   date.setTime(+date + step * durationHour);
24556 }, function(start, end) {
24557   return (end - start) / durationHour;
24558 }, function(date) {
24559   return date.getUTCHours();
24560 });
24561
24562 var utcHours = utcHour.range;
24563
24564 var utcDay = newInterval(function(date) {
24565   date.setUTCHours(0, 0, 0, 0);
24566 }, function(date, step) {
24567   date.setUTCDate(date.getUTCDate() + step);
24568 }, function(start, end) {
24569   return (end - start) / durationDay;
24570 }, function(date) {
24571   return date.getUTCDate() - 1;
24572 });
24573
24574 var utcDays = utcDay.range;
24575
24576 function utcWeekday(i) {
24577   return newInterval(function(date) {
24578     date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
24579     date.setUTCHours(0, 0, 0, 0);
24580   }, function(date, step) {
24581     date.setUTCDate(date.getUTCDate() + step * 7);
24582   }, function(start, end) {
24583     return (end - start) / durationWeek;
24584   });
24585 }
24586
24587 var utcSunday = utcWeekday(0);
24588 var utcMonday = utcWeekday(1);
24589 var utcTuesday = utcWeekday(2);
24590 var utcWednesday = utcWeekday(3);
24591 var utcThursday = utcWeekday(4);
24592 var utcFriday = utcWeekday(5);
24593 var utcSaturday = utcWeekday(6);
24594
24595 var utcSundays = utcSunday.range;
24596 var utcMondays = utcMonday.range;
24597 var utcTuesdays = utcTuesday.range;
24598 var utcWednesdays = utcWednesday.range;
24599 var utcThursdays = utcThursday.range;
24600 var utcFridays = utcFriday.range;
24601 var utcSaturdays = utcSaturday.range;
24602
24603 var utcMonth = newInterval(function(date) {
24604   date.setUTCDate(1);
24605   date.setUTCHours(0, 0, 0, 0);
24606 }, function(date, step) {
24607   date.setUTCMonth(date.getUTCMonth() + step);
24608 }, function(start, end) {
24609   return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
24610 }, function(date) {
24611   return date.getUTCMonth();
24612 });
24613
24614 var utcMonths = utcMonth.range;
24615
24616 var utcYear = newInterval(function(date) {
24617   date.setUTCMonth(0, 1);
24618   date.setUTCHours(0, 0, 0, 0);
24619 }, function(date, step) {
24620   date.setUTCFullYear(date.getUTCFullYear() + step);
24621 }, function(start, end) {
24622   return end.getUTCFullYear() - start.getUTCFullYear();
24623 }, function(date) {
24624   return date.getUTCFullYear();
24625 });
24626
24627 // An optimized implementation for this simple case.
24628 utcYear.every = function(k) {
24629   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
24630     date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
24631     date.setUTCMonth(0, 1);
24632     date.setUTCHours(0, 0, 0, 0);
24633   }, function(date, step) {
24634     date.setUTCFullYear(date.getUTCFullYear() + step * k);
24635   });
24636 };
24637
24638 var utcYears = utcYear.range;
24639
24640 // Computes the decimal coefficient and exponent of the specified number x with
24641 // significant digits p, where x is positive and p is in [1, 21] or undefined.
24642 // For example, formatDecimal(1.23) returns ["123", 0].
24643 var formatDecimal = function(x, p) {
24644   if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
24645   var i, coefficient = x.slice(0, i);
24646
24647   // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
24648   // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
24649   return [
24650     coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
24651     +x.slice(i + 1)
24652   ];
24653 };
24654
24655 var exponent$1 = function(x) {
24656   return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
24657 };
24658
24659 var formatGroup = function(grouping, thousands) {
24660   return function(value, width) {
24661     var i = value.length,
24662         t = [],
24663         j = 0,
24664         g = grouping[0],
24665         length = 0;
24666
24667     while (i > 0 && g > 0) {
24668       if (length + g + 1 > width) g = Math.max(1, width - length);
24669       t.push(value.substring(i -= g, i + g));
24670       if ((length += g + 1) > width) break;
24671       g = grouping[j = (j + 1) % grouping.length];
24672     }
24673
24674     return t.reverse().join(thousands);
24675   };
24676 };
24677
24678 var formatDefault = function(x, p) {
24679   x = x.toPrecision(p);
24680
24681   out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
24682     switch (x[i]) {
24683       case ".": i0 = i1 = i; break;
24684       case "0": if (i0 === 0) i0 = i; i1 = i; break;
24685       case "e": break out;
24686       default: if (i0 > 0) i0 = 0; break;
24687     }
24688   }
24689
24690   return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
24691 };
24692
24693 var prefixExponent;
24694
24695 var formatPrefixAuto = function(x, p) {
24696   var d = formatDecimal(x, p);
24697   if (!d) return x + "";
24698   var coefficient = d[0],
24699       exponent = d[1],
24700       i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
24701       n = coefficient.length;
24702   return i === n ? coefficient
24703       : i > n ? coefficient + new Array(i - n + 1).join("0")
24704       : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
24705       : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
24706 };
24707
24708 var formatRounded = function(x, p) {
24709   var d = formatDecimal(x, p);
24710   if (!d) return x + "";
24711   var coefficient = d[0],
24712       exponent = d[1];
24713   return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
24714       : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
24715       : coefficient + new Array(exponent - coefficient.length + 2).join("0");
24716 };
24717
24718 var formatTypes = {
24719   "": formatDefault,
24720   "%": function(x, p) { return (x * 100).toFixed(p); },
24721   "b": function(x) { return Math.round(x).toString(2); },
24722   "c": function(x) { return x + ""; },
24723   "d": function(x) { return Math.round(x).toString(10); },
24724   "e": function(x, p) { return x.toExponential(p); },
24725   "f": function(x, p) { return x.toFixed(p); },
24726   "g": function(x, p) { return x.toPrecision(p); },
24727   "o": function(x) { return Math.round(x).toString(8); },
24728   "p": function(x, p) { return formatRounded(x * 100, p); },
24729   "r": formatRounded,
24730   "s": formatPrefixAuto,
24731   "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
24732   "x": function(x) { return Math.round(x).toString(16); }
24733 };
24734
24735 // [[fill]align][sign][symbol][0][width][,][.precision][type]
24736 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
24737
24738 var formatSpecifier = function(specifier) {
24739   return new FormatSpecifier(specifier);
24740 };
24741
24742 function FormatSpecifier(specifier) {
24743   if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
24744
24745   var match,
24746       fill = match[1] || " ",
24747       align = match[2] || ">",
24748       sign = match[3] || "-",
24749       symbol = match[4] || "",
24750       zero = !!match[5],
24751       width = match[6] && +match[6],
24752       comma = !!match[7],
24753       precision = match[8] && +match[8].slice(1),
24754       type = match[9] || "";
24755
24756   // The "n" type is an alias for ",g".
24757   if (type === "n") comma = true, type = "g";
24758
24759   // Map invalid types to the default format.
24760   else if (!formatTypes[type]) type = "";
24761
24762   // If zero fill is specified, padding goes after sign and before digits.
24763   if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
24764
24765   this.fill = fill;
24766   this.align = align;
24767   this.sign = sign;
24768   this.symbol = symbol;
24769   this.zero = zero;
24770   this.width = width;
24771   this.comma = comma;
24772   this.precision = precision;
24773   this.type = type;
24774 }
24775
24776 FormatSpecifier.prototype.toString = function() {
24777   return this.fill
24778       + this.align
24779       + this.sign
24780       + this.symbol
24781       + (this.zero ? "0" : "")
24782       + (this.width == null ? "" : Math.max(1, this.width | 0))
24783       + (this.comma ? "," : "")
24784       + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
24785       + this.type;
24786 };
24787
24788 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
24789
24790 function identity$3(x) {
24791   return x;
24792 }
24793
24794 var formatLocale = function(locale) {
24795   var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
24796       currency = locale.currency,
24797       decimal = locale.decimal;
24798
24799   function newFormat(specifier) {
24800     specifier = formatSpecifier(specifier);
24801
24802     var fill = specifier.fill,
24803         align = specifier.align,
24804         sign = specifier.sign,
24805         symbol = specifier.symbol,
24806         zero = specifier.zero,
24807         width = specifier.width,
24808         comma = specifier.comma,
24809         precision = specifier.precision,
24810         type = specifier.type;
24811
24812     // Compute the prefix and suffix.
24813     // For SI-prefix, the suffix is lazily computed.
24814     var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
24815         suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
24816
24817     // What format function should we use?
24818     // Is this an integer type?
24819     // Can this type generate exponential notation?
24820     var formatType = formatTypes[type],
24821         maybeSuffix = !type || /[defgprs%]/.test(type);
24822
24823     // Set the default precision if not specified,
24824     // or clamp the specified precision to the supported range.
24825     // For significant precision, it must be in [1, 21].
24826     // For fixed precision, it must be in [0, 20].
24827     precision = precision == null ? (type ? 6 : 12)
24828         : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
24829         : Math.max(0, Math.min(20, precision));
24830
24831     function format(value) {
24832       var valuePrefix = prefix,
24833           valueSuffix = suffix,
24834           i, n, c;
24835
24836       if (type === "c") {
24837         valueSuffix = formatType(value) + valueSuffix;
24838         value = "";
24839       } else {
24840         value = +value;
24841
24842         // Convert negative to positive, and compute the prefix.
24843         // Note that -0 is not less than 0, but 1 / -0 is!
24844         var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
24845
24846         // Perform the initial formatting.
24847         value = formatType(value, precision);
24848
24849         // If the original value was negative, it may be rounded to zero during
24850         // formatting; treat this as (positive) zero.
24851         if (valueNegative) {
24852           i = -1, n = value.length;
24853           valueNegative = false;
24854           while (++i < n) {
24855             if (c = value.charCodeAt(i), (48 < c && c < 58)
24856                 || (type === "x" && 96 < c && c < 103)
24857                 || (type === "X" && 64 < c && c < 71)) {
24858               valueNegative = true;
24859               break;
24860             }
24861           }
24862         }
24863
24864         // Compute the prefix and suffix.
24865         valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
24866         valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
24867
24868         // Break the formatted value into the integer “value” part that can be
24869         // grouped, and fractional or exponential “suffix” part that is not.
24870         if (maybeSuffix) {
24871           i = -1, n = value.length;
24872           while (++i < n) {
24873             if (c = value.charCodeAt(i), 48 > c || c > 57) {
24874               valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
24875               value = value.slice(0, i);
24876               break;
24877             }
24878           }
24879         }
24880       }
24881
24882       // If the fill character is not "0", grouping is applied before padding.
24883       if (comma && !zero) value = group(value, Infinity);
24884
24885       // Compute the padding.
24886       var length = valuePrefix.length + value.length + valueSuffix.length,
24887           padding = length < width ? new Array(width - length + 1).join(fill) : "";
24888
24889       // If the fill character is "0", grouping is applied after padding.
24890       if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
24891
24892       // Reconstruct the final output based on the desired alignment.
24893       switch (align) {
24894         case "<": return valuePrefix + value + valueSuffix + padding;
24895         case "=": return valuePrefix + padding + value + valueSuffix;
24896         case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
24897       }
24898       return padding + valuePrefix + value + valueSuffix;
24899     }
24900
24901     format.toString = function() {
24902       return specifier + "";
24903     };
24904
24905     return format;
24906   }
24907
24908   function formatPrefix(specifier, value) {
24909     var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
24910         e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
24911         k = Math.pow(10, -e),
24912         prefix = prefixes[8 + e / 3];
24913     return function(value) {
24914       return f(k * value) + prefix;
24915     };
24916   }
24917
24918   return {
24919     format: newFormat,
24920     formatPrefix: formatPrefix
24921   };
24922 };
24923
24924 var locale$1;
24925 var format;
24926 var formatPrefix;
24927
24928 defaultLocale({
24929   decimal: ".",
24930   thousands: ",",
24931   grouping: [3],
24932   currency: ["$", ""]
24933 });
24934
24935 function defaultLocale(definition) {
24936   locale$1 = formatLocale(definition);
24937   format = locale$1.format;
24938   formatPrefix = locale$1.formatPrefix;
24939   return locale$1;
24940 }
24941
24942 var precisionFixed = function(step) {
24943   return Math.max(0, -exponent$1(Math.abs(step)));
24944 };
24945
24946 var precisionPrefix = function(step, value) {
24947   return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
24948 };
24949
24950 var precisionRound = function(step, max) {
24951   step = Math.abs(step), max = Math.abs(max) - step;
24952   return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
24953 };
24954
24955 function localDate(d) {
24956   if (0 <= d.y && d.y < 100) {
24957     var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
24958     date.setFullYear(d.y);
24959     return date;
24960   }
24961   return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
24962 }
24963
24964 function utcDate(d) {
24965   if (0 <= d.y && d.y < 100) {
24966     var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
24967     date.setUTCFullYear(d.y);
24968     return date;
24969   }
24970   return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
24971 }
24972
24973 function newYear(y) {
24974   return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
24975 }
24976
24977 function formatLocale$1(locale) {
24978   var locale_dateTime = locale.dateTime,
24979       locale_date = locale.date,
24980       locale_time = locale.time,
24981       locale_periods = locale.periods,
24982       locale_weekdays = locale.days,
24983       locale_shortWeekdays = locale.shortDays,
24984       locale_months = locale.months,
24985       locale_shortMonths = locale.shortMonths;
24986
24987   var periodRe = formatRe(locale_periods),
24988       periodLookup = formatLookup(locale_periods),
24989       weekdayRe = formatRe(locale_weekdays),
24990       weekdayLookup = formatLookup(locale_weekdays),
24991       shortWeekdayRe = formatRe(locale_shortWeekdays),
24992       shortWeekdayLookup = formatLookup(locale_shortWeekdays),
24993       monthRe = formatRe(locale_months),
24994       monthLookup = formatLookup(locale_months),
24995       shortMonthRe = formatRe(locale_shortMonths),
24996       shortMonthLookup = formatLookup(locale_shortMonths);
24997
24998   var formats = {
24999     "a": formatShortWeekday,
25000     "A": formatWeekday,
25001     "b": formatShortMonth,
25002     "B": formatMonth,
25003     "c": null,
25004     "d": formatDayOfMonth,
25005     "e": formatDayOfMonth,
25006     "H": formatHour24,
25007     "I": formatHour12,
25008     "j": formatDayOfYear,
25009     "L": formatMilliseconds,
25010     "m": formatMonthNumber,
25011     "M": formatMinutes,
25012     "p": formatPeriod,
25013     "S": formatSeconds,
25014     "U": formatWeekNumberSunday,
25015     "w": formatWeekdayNumber,
25016     "W": formatWeekNumberMonday,
25017     "x": null,
25018     "X": null,
25019     "y": formatYear,
25020     "Y": formatFullYear,
25021     "Z": formatZone,
25022     "%": formatLiteralPercent
25023   };
25024
25025   var utcFormats = {
25026     "a": formatUTCShortWeekday,
25027     "A": formatUTCWeekday,
25028     "b": formatUTCShortMonth,
25029     "B": formatUTCMonth,
25030     "c": null,
25031     "d": formatUTCDayOfMonth,
25032     "e": formatUTCDayOfMonth,
25033     "H": formatUTCHour24,
25034     "I": formatUTCHour12,
25035     "j": formatUTCDayOfYear,
25036     "L": formatUTCMilliseconds,
25037     "m": formatUTCMonthNumber,
25038     "M": formatUTCMinutes,
25039     "p": formatUTCPeriod,
25040     "S": formatUTCSeconds,
25041     "U": formatUTCWeekNumberSunday,
25042     "w": formatUTCWeekdayNumber,
25043     "W": formatUTCWeekNumberMonday,
25044     "x": null,
25045     "X": null,
25046     "y": formatUTCYear,
25047     "Y": formatUTCFullYear,
25048     "Z": formatUTCZone,
25049     "%": formatLiteralPercent
25050   };
25051
25052   var parses = {
25053     "a": parseShortWeekday,
25054     "A": parseWeekday,
25055     "b": parseShortMonth,
25056     "B": parseMonth,
25057     "c": parseLocaleDateTime,
25058     "d": parseDayOfMonth,
25059     "e": parseDayOfMonth,
25060     "H": parseHour24,
25061     "I": parseHour24,
25062     "j": parseDayOfYear,
25063     "L": parseMilliseconds,
25064     "m": parseMonthNumber,
25065     "M": parseMinutes,
25066     "p": parsePeriod,
25067     "S": parseSeconds,
25068     "U": parseWeekNumberSunday,
25069     "w": parseWeekdayNumber,
25070     "W": parseWeekNumberMonday,
25071     "x": parseLocaleDate,
25072     "X": parseLocaleTime,
25073     "y": parseYear,
25074     "Y": parseFullYear,
25075     "Z": parseZone,
25076     "%": parseLiteralPercent
25077   };
25078
25079   // These recursive directive definitions must be deferred.
25080   formats.x = newFormat(locale_date, formats);
25081   formats.X = newFormat(locale_time, formats);
25082   formats.c = newFormat(locale_dateTime, formats);
25083   utcFormats.x = newFormat(locale_date, utcFormats);
25084   utcFormats.X = newFormat(locale_time, utcFormats);
25085   utcFormats.c = newFormat(locale_dateTime, utcFormats);
25086
25087   function newFormat(specifier, formats) {
25088     return function(date) {
25089       var string = [],
25090           i = -1,
25091           j = 0,
25092           n = specifier.length,
25093           c,
25094           pad,
25095           format;
25096
25097       if (!(date instanceof Date)) date = new Date(+date);
25098
25099       while (++i < n) {
25100         if (specifier.charCodeAt(i) === 37) {
25101           string.push(specifier.slice(j, i));
25102           if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
25103           else pad = c === "e" ? " " : "0";
25104           if (format = formats[c]) c = format(date, pad);
25105           string.push(c);
25106           j = i + 1;
25107         }
25108       }
25109
25110       string.push(specifier.slice(j, i));
25111       return string.join("");
25112     };
25113   }
25114
25115   function newParse(specifier, newDate) {
25116     return function(string) {
25117       var d = newYear(1900),
25118           i = parseSpecifier(d, specifier, string += "", 0);
25119       if (i != string.length) return null;
25120
25121       // The am-pm flag is 0 for AM, and 1 for PM.
25122       if ("p" in d) d.H = d.H % 12 + d.p * 12;
25123
25124       // Convert day-of-week and week-of-year to day-of-year.
25125       if ("W" in d || "U" in d) {
25126         if (!("w" in d)) d.w = "W" in d ? 1 : 0;
25127         var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
25128         d.m = 0;
25129         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;
25130       }
25131
25132       // If a time zone is specified, all fields are interpreted as UTC and then
25133       // offset according to the specified time zone.
25134       if ("Z" in d) {
25135         d.H += d.Z / 100 | 0;
25136         d.M += d.Z % 100;
25137         return utcDate(d);
25138       }
25139
25140       // Otherwise, all fields are in local time.
25141       return newDate(d);
25142     };
25143   }
25144
25145   function parseSpecifier(d, specifier, string, j) {
25146     var i = 0,
25147         n = specifier.length,
25148         m = string.length,
25149         c,
25150         parse;
25151
25152     while (i < n) {
25153       if (j >= m) return -1;
25154       c = specifier.charCodeAt(i++);
25155       if (c === 37) {
25156         c = specifier.charAt(i++);
25157         parse = parses[c in pads ? specifier.charAt(i++) : c];
25158         if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
25159       } else if (c != string.charCodeAt(j++)) {
25160         return -1;
25161       }
25162     }
25163
25164     return j;
25165   }
25166
25167   function parsePeriod(d, string, i) {
25168     var n = periodRe.exec(string.slice(i));
25169     return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25170   }
25171
25172   function parseShortWeekday(d, string, i) {
25173     var n = shortWeekdayRe.exec(string.slice(i));
25174     return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25175   }
25176
25177   function parseWeekday(d, string, i) {
25178     var n = weekdayRe.exec(string.slice(i));
25179     return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25180   }
25181
25182   function parseShortMonth(d, string, i) {
25183     var n = shortMonthRe.exec(string.slice(i));
25184     return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25185   }
25186
25187   function parseMonth(d, string, i) {
25188     var n = monthRe.exec(string.slice(i));
25189     return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25190   }
25191
25192   function parseLocaleDateTime(d, string, i) {
25193     return parseSpecifier(d, locale_dateTime, string, i);
25194   }
25195
25196   function parseLocaleDate(d, string, i) {
25197     return parseSpecifier(d, locale_date, string, i);
25198   }
25199
25200   function parseLocaleTime(d, string, i) {
25201     return parseSpecifier(d, locale_time, string, i);
25202   }
25203
25204   function formatShortWeekday(d) {
25205     return locale_shortWeekdays[d.getDay()];
25206   }
25207
25208   function formatWeekday(d) {
25209     return locale_weekdays[d.getDay()];
25210   }
25211
25212   function formatShortMonth(d) {
25213     return locale_shortMonths[d.getMonth()];
25214   }
25215
25216   function formatMonth(d) {
25217     return locale_months[d.getMonth()];
25218   }
25219
25220   function formatPeriod(d) {
25221     return locale_periods[+(d.getHours() >= 12)];
25222   }
25223
25224   function formatUTCShortWeekday(d) {
25225     return locale_shortWeekdays[d.getUTCDay()];
25226   }
25227
25228   function formatUTCWeekday(d) {
25229     return locale_weekdays[d.getUTCDay()];
25230   }
25231
25232   function formatUTCShortMonth(d) {
25233     return locale_shortMonths[d.getUTCMonth()];
25234   }
25235
25236   function formatUTCMonth(d) {
25237     return locale_months[d.getUTCMonth()];
25238   }
25239
25240   function formatUTCPeriod(d) {
25241     return locale_periods[+(d.getUTCHours() >= 12)];
25242   }
25243
25244   return {
25245     format: function(specifier) {
25246       var f = newFormat(specifier += "", formats);
25247       f.toString = function() { return specifier; };
25248       return f;
25249     },
25250     parse: function(specifier) {
25251       var p = newParse(specifier += "", localDate);
25252       p.toString = function() { return specifier; };
25253       return p;
25254     },
25255     utcFormat: function(specifier) {
25256       var f = newFormat(specifier += "", utcFormats);
25257       f.toString = function() { return specifier; };
25258       return f;
25259     },
25260     utcParse: function(specifier) {
25261       var p = newParse(specifier, utcDate);
25262       p.toString = function() { return specifier; };
25263       return p;
25264     }
25265   };
25266 }
25267
25268 var pads = {"-": "", "_": " ", "0": "0"};
25269 var numberRe = /^\s*\d+/;
25270 var percentRe = /^%/;
25271 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
25272
25273 function pad(value, fill, width) {
25274   var sign = value < 0 ? "-" : "",
25275       string = (sign ? -value : value) + "",
25276       length = string.length;
25277   return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
25278 }
25279
25280 function requote(s) {
25281   return s.replace(requoteRe, "\\$&");
25282 }
25283
25284 function formatRe(names) {
25285   return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
25286 }
25287
25288 function formatLookup(names) {
25289   var map = {}, i = -1, n = names.length;
25290   while (++i < n) map[names[i].toLowerCase()] = i;
25291   return map;
25292 }
25293
25294 function parseWeekdayNumber(d, string, i) {
25295   var n = numberRe.exec(string.slice(i, i + 1));
25296   return n ? (d.w = +n[0], i + n[0].length) : -1;
25297 }
25298
25299 function parseWeekNumberSunday(d, string, i) {
25300   var n = numberRe.exec(string.slice(i));
25301   return n ? (d.U = +n[0], i + n[0].length) : -1;
25302 }
25303
25304 function parseWeekNumberMonday(d, string, i) {
25305   var n = numberRe.exec(string.slice(i));
25306   return n ? (d.W = +n[0], i + n[0].length) : -1;
25307 }
25308
25309 function parseFullYear(d, string, i) {
25310   var n = numberRe.exec(string.slice(i, i + 4));
25311   return n ? (d.y = +n[0], i + n[0].length) : -1;
25312 }
25313
25314 function parseYear(d, string, i) {
25315   var n = numberRe.exec(string.slice(i, i + 2));
25316   return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
25317 }
25318
25319 function parseZone(d, string, i) {
25320   var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
25321   return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
25322 }
25323
25324 function parseMonthNumber(d, string, i) {
25325   var n = numberRe.exec(string.slice(i, i + 2));
25326   return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
25327 }
25328
25329 function parseDayOfMonth(d, string, i) {
25330   var n = numberRe.exec(string.slice(i, i + 2));
25331   return n ? (d.d = +n[0], i + n[0].length) : -1;
25332 }
25333
25334 function parseDayOfYear(d, string, i) {
25335   var n = numberRe.exec(string.slice(i, i + 3));
25336   return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
25337 }
25338
25339 function parseHour24(d, string, i) {
25340   var n = numberRe.exec(string.slice(i, i + 2));
25341   return n ? (d.H = +n[0], i + n[0].length) : -1;
25342 }
25343
25344 function parseMinutes(d, string, i) {
25345   var n = numberRe.exec(string.slice(i, i + 2));
25346   return n ? (d.M = +n[0], i + n[0].length) : -1;
25347 }
25348
25349 function parseSeconds(d, string, i) {
25350   var n = numberRe.exec(string.slice(i, i + 2));
25351   return n ? (d.S = +n[0], i + n[0].length) : -1;
25352 }
25353
25354 function parseMilliseconds(d, string, i) {
25355   var n = numberRe.exec(string.slice(i, i + 3));
25356   return n ? (d.L = +n[0], i + n[0].length) : -1;
25357 }
25358
25359 function parseLiteralPercent(d, string, i) {
25360   var n = percentRe.exec(string.slice(i, i + 1));
25361   return n ? i + n[0].length : -1;
25362 }
25363
25364 function formatDayOfMonth(d, p) {
25365   return pad(d.getDate(), p, 2);
25366 }
25367
25368 function formatHour24(d, p) {
25369   return pad(d.getHours(), p, 2);
25370 }
25371
25372 function formatHour12(d, p) {
25373   return pad(d.getHours() % 12 || 12, p, 2);
25374 }
25375
25376 function formatDayOfYear(d, p) {
25377   return pad(1 + day.count(year(d), d), p, 3);
25378 }
25379
25380 function formatMilliseconds(d, p) {
25381   return pad(d.getMilliseconds(), p, 3);
25382 }
25383
25384 function formatMonthNumber(d, p) {
25385   return pad(d.getMonth() + 1, p, 2);
25386 }
25387
25388 function formatMinutes(d, p) {
25389   return pad(d.getMinutes(), p, 2);
25390 }
25391
25392 function formatSeconds(d, p) {
25393   return pad(d.getSeconds(), p, 2);
25394 }
25395
25396 function formatWeekNumberSunday(d, p) {
25397   return pad(sunday.count(year(d), d), p, 2);
25398 }
25399
25400 function formatWeekdayNumber(d) {
25401   return d.getDay();
25402 }
25403
25404 function formatWeekNumberMonday(d, p) {
25405   return pad(monday.count(year(d), d), p, 2);
25406 }
25407
25408 function formatYear(d, p) {
25409   return pad(d.getFullYear() % 100, p, 2);
25410 }
25411
25412 function formatFullYear(d, p) {
25413   return pad(d.getFullYear() % 10000, p, 4);
25414 }
25415
25416 function formatZone(d) {
25417   var z = d.getTimezoneOffset();
25418   return (z > 0 ? "-" : (z *= -1, "+"))
25419       + pad(z / 60 | 0, "0", 2)
25420       + pad(z % 60, "0", 2);
25421 }
25422
25423 function formatUTCDayOfMonth(d, p) {
25424   return pad(d.getUTCDate(), p, 2);
25425 }
25426
25427 function formatUTCHour24(d, p) {
25428   return pad(d.getUTCHours(), p, 2);
25429 }
25430
25431 function formatUTCHour12(d, p) {
25432   return pad(d.getUTCHours() % 12 || 12, p, 2);
25433 }
25434
25435 function formatUTCDayOfYear(d, p) {
25436   return pad(1 + utcDay.count(utcYear(d), d), p, 3);
25437 }
25438
25439 function formatUTCMilliseconds(d, p) {
25440   return pad(d.getUTCMilliseconds(), p, 3);
25441 }
25442
25443 function formatUTCMonthNumber(d, p) {
25444   return pad(d.getUTCMonth() + 1, p, 2);
25445 }
25446
25447 function formatUTCMinutes(d, p) {
25448   return pad(d.getUTCMinutes(), p, 2);
25449 }
25450
25451 function formatUTCSeconds(d, p) {
25452   return pad(d.getUTCSeconds(), p, 2);
25453 }
25454
25455 function formatUTCWeekNumberSunday(d, p) {
25456   return pad(utcSunday.count(utcYear(d), d), p, 2);
25457 }
25458
25459 function formatUTCWeekdayNumber(d) {
25460   return d.getUTCDay();
25461 }
25462
25463 function formatUTCWeekNumberMonday(d, p) {
25464   return pad(utcMonday.count(utcYear(d), d), p, 2);
25465 }
25466
25467 function formatUTCYear(d, p) {
25468   return pad(d.getUTCFullYear() % 100, p, 2);
25469 }
25470
25471 function formatUTCFullYear(d, p) {
25472   return pad(d.getUTCFullYear() % 10000, p, 4);
25473 }
25474
25475 function formatUTCZone() {
25476   return "+0000";
25477 }
25478
25479 function formatLiteralPercent() {
25480   return "%";
25481 }
25482
25483 var locale$2;
25484 var timeFormat;
25485 var timeParse;
25486 var utcFormat;
25487 var utcParse;
25488
25489 defaultLocale$1({
25490   dateTime: "%x, %X",
25491   date: "%-m/%-d/%Y",
25492   time: "%-I:%M:%S %p",
25493   periods: ["AM", "PM"],
25494   days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
25495   shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
25496   months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
25497   shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
25498 });
25499
25500 function defaultLocale$1(definition) {
25501   locale$2 = formatLocale$1(definition);
25502   timeFormat = locale$2.format;
25503   timeParse = locale$2.parse;
25504   utcFormat = locale$2.utcFormat;
25505   utcParse = locale$2.utcParse;
25506   return locale$2;
25507 }
25508
25509 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
25510
25511 function formatIsoNative(date) {
25512   return date.toISOString();
25513 }
25514
25515 var formatIso = Date.prototype.toISOString
25516     ? formatIsoNative
25517     : utcFormat(isoSpecifier);
25518
25519 function parseIsoNative(string) {
25520   var date = new Date(string);
25521   return isNaN(date) ? null : date;
25522 }
25523
25524 var parseIso = +new Date("2000-01-01T00:00:00.000Z")
25525     ? parseIsoNative
25526     : utcParse(isoSpecifier);
25527
25528 var array$2 = Array.prototype;
25529
25530 var map$3 = array$2.map;
25531 var slice$3 = array$2.slice;
25532
25533 var implicit = {name: "implicit"};
25534
25535 function ordinal(range) {
25536   var index = map$1(),
25537       domain = [],
25538       unknown = implicit;
25539
25540   range = range == null ? [] : slice$3.call(range);
25541
25542   function scale(d) {
25543     var key = d + "", i = index.get(key);
25544     if (!i) {
25545       if (unknown !== implicit) return unknown;
25546       index.set(key, i = domain.push(d));
25547     }
25548     return range[(i - 1) % range.length];
25549   }
25550
25551   scale.domain = function(_) {
25552     if (!arguments.length) return domain.slice();
25553     domain = [], index = map$1();
25554     var i = -1, n = _.length, d, key;
25555     while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
25556     return scale;
25557   };
25558
25559   scale.range = function(_) {
25560     return arguments.length ? (range = slice$3.call(_), scale) : range.slice();
25561   };
25562
25563   scale.unknown = function(_) {
25564     return arguments.length ? (unknown = _, scale) : unknown;
25565   };
25566
25567   scale.copy = function() {
25568     return ordinal()
25569         .domain(domain)
25570         .range(range)
25571         .unknown(unknown);
25572   };
25573
25574   return scale;
25575 }
25576
25577 function band() {
25578   var scale = ordinal().unknown(undefined),
25579       domain = scale.domain,
25580       ordinalRange = scale.range,
25581       range$$1 = [0, 1],
25582       step,
25583       bandwidth,
25584       round = false,
25585       paddingInner = 0,
25586       paddingOuter = 0,
25587       align = 0.5;
25588
25589   delete scale.unknown;
25590
25591   function rescale() {
25592     var n = domain().length,
25593         reverse = range$$1[1] < range$$1[0],
25594         start = range$$1[reverse - 0],
25595         stop = range$$1[1 - reverse];
25596     step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
25597     if (round) step = Math.floor(step);
25598     start += (stop - start - step * (n - paddingInner)) * align;
25599     bandwidth = step * (1 - paddingInner);
25600     if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
25601     var values = range(n).map(function(i) { return start + step * i; });
25602     return ordinalRange(reverse ? values.reverse() : values);
25603   }
25604
25605   scale.domain = function(_) {
25606     return arguments.length ? (domain(_), rescale()) : domain();
25607   };
25608
25609   scale.range = function(_) {
25610     return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice();
25611   };
25612
25613   scale.rangeRound = function(_) {
25614     return range$$1 = [+_[0], +_[1]], round = true, rescale();
25615   };
25616
25617   scale.bandwidth = function() {
25618     return bandwidth;
25619   };
25620
25621   scale.step = function() {
25622     return step;
25623   };
25624
25625   scale.round = function(_) {
25626     return arguments.length ? (round = !!_, rescale()) : round;
25627   };
25628
25629   scale.padding = function(_) {
25630     return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
25631   };
25632
25633   scale.paddingInner = function(_) {
25634     return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
25635   };
25636
25637   scale.paddingOuter = function(_) {
25638     return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
25639   };
25640
25641   scale.align = function(_) {
25642     return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
25643   };
25644
25645   scale.copy = function() {
25646     return band()
25647         .domain(domain())
25648         .range(range$$1)
25649         .round(round)
25650         .paddingInner(paddingInner)
25651         .paddingOuter(paddingOuter)
25652         .align(align);
25653   };
25654
25655   return rescale();
25656 }
25657
25658 function pointish(scale) {
25659   var copy = scale.copy;
25660
25661   scale.padding = scale.paddingOuter;
25662   delete scale.paddingInner;
25663   delete scale.paddingOuter;
25664
25665   scale.copy = function() {
25666     return pointish(copy());
25667   };
25668
25669   return scale;
25670 }
25671
25672 function point$4() {
25673   return pointish(band().paddingInner(1));
25674 }
25675
25676 var constant$4 = function(x) {
25677   return function() {
25678     return x;
25679   };
25680 };
25681
25682 var number$1 = function(x) {
25683   return +x;
25684 };
25685
25686 var unit = [0, 1];
25687
25688 function deinterpolateLinear(a, b) {
25689   return (b -= (a = +a))
25690       ? function(x) { return (x - a) / b; }
25691       : constant$4(b);
25692 }
25693
25694 function deinterpolateClamp(deinterpolate) {
25695   return function(a, b) {
25696     var d = deinterpolate(a = +a, b = +b);
25697     return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
25698   };
25699 }
25700
25701 function reinterpolateClamp(reinterpolate) {
25702   return function(a, b) {
25703     var r = reinterpolate(a = +a, b = +b);
25704     return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
25705   };
25706 }
25707
25708 function bimap(domain, range$$1, deinterpolate, reinterpolate) {
25709   var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1];
25710   if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
25711   else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
25712   return function(x) { return r0(d0(x)); };
25713 }
25714
25715 function polymap(domain, range$$1, deinterpolate, reinterpolate) {
25716   var j = Math.min(domain.length, range$$1.length) - 1,
25717       d = new Array(j),
25718       r = new Array(j),
25719       i = -1;
25720
25721   // Reverse descending domains.
25722   if (domain[j] < domain[0]) {
25723     domain = domain.slice().reverse();
25724     range$$1 = range$$1.slice().reverse();
25725   }
25726
25727   while (++i < j) {
25728     d[i] = deinterpolate(domain[i], domain[i + 1]);
25729     r[i] = reinterpolate(range$$1[i], range$$1[i + 1]);
25730   }
25731
25732   return function(x) {
25733     var i = bisectRight(domain, x, 1, j) - 1;
25734     return r[i](d[i](x));
25735   };
25736 }
25737
25738 function copy(source, target) {
25739   return target
25740       .domain(source.domain())
25741       .range(source.range())
25742       .interpolate(source.interpolate())
25743       .clamp(source.clamp());
25744 }
25745
25746 // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
25747 // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
25748 function continuous(deinterpolate, reinterpolate) {
25749   var domain = unit,
25750       range$$1 = unit,
25751       interpolate$$1 = interpolate,
25752       clamp = false,
25753       piecewise,
25754       output,
25755       input;
25756
25757   function rescale() {
25758     piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap;
25759     output = input = null;
25760     return scale;
25761   }
25762
25763   function scale(x) {
25764     return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x);
25765   }
25766
25767   scale.invert = function(y) {
25768     return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
25769   };
25770
25771   scale.domain = function(_) {
25772     return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice();
25773   };
25774
25775   scale.range = function(_) {
25776     return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice();
25777   };
25778
25779   scale.rangeRound = function(_) {
25780     return range$$1 = slice$3.call(_), interpolate$$1 = interpolateRound, rescale();
25781   };
25782
25783   scale.clamp = function(_) {
25784     return arguments.length ? (clamp = !!_, rescale()) : clamp;
25785   };
25786
25787   scale.interpolate = function(_) {
25788     return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1;
25789   };
25790
25791   return rescale();
25792 }
25793
25794 var tickFormat = function(domain, count, specifier) {
25795   var start = domain[0],
25796       stop = domain[domain.length - 1],
25797       step = tickStep(start, stop, count == null ? 10 : count),
25798       precision;
25799   specifier = formatSpecifier(specifier == null ? ",f" : specifier);
25800   switch (specifier.type) {
25801     case "s": {
25802       var value = Math.max(Math.abs(start), Math.abs(stop));
25803       if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
25804       return formatPrefix(specifier, value);
25805     }
25806     case "":
25807     case "e":
25808     case "g":
25809     case "p":
25810     case "r": {
25811       if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
25812       break;
25813     }
25814     case "f":
25815     case "%": {
25816       if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
25817       break;
25818     }
25819   }
25820   return format(specifier);
25821 };
25822
25823 function linearish(scale) {
25824   var domain = scale.domain;
25825
25826   scale.ticks = function(count) {
25827     var d = domain();
25828     return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
25829   };
25830
25831   scale.tickFormat = function(count, specifier) {
25832     return tickFormat(domain(), count, specifier);
25833   };
25834
25835   scale.nice = function(count) {
25836     var d = domain(),
25837         i = d.length - 1,
25838         n = count == null ? 10 : count,
25839         start = d[0],
25840         stop = d[i],
25841         step = tickStep(start, stop, n);
25842
25843     if (step) {
25844       step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n);
25845       d[0] = Math.floor(start / step) * step;
25846       d[i] = Math.ceil(stop / step) * step;
25847       domain(d);
25848     }
25849
25850     return scale;
25851   };
25852
25853   return scale;
25854 }
25855
25856 function linear$2() {
25857   var scale = continuous(deinterpolateLinear, interpolateNumber);
25858
25859   scale.copy = function() {
25860     return copy(scale, linear$2());
25861   };
25862
25863   return linearish(scale);
25864 }
25865
25866 function identity$4() {
25867   var domain = [0, 1];
25868
25869   function scale(x) {
25870     return +x;
25871   }
25872
25873   scale.invert = scale;
25874
25875   scale.domain = scale.range = function(_) {
25876     return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice();
25877   };
25878
25879   scale.copy = function() {
25880     return identity$4().domain(domain);
25881   };
25882
25883   return linearish(scale);
25884 }
25885
25886 var nice = function(domain, interval) {
25887   domain = domain.slice();
25888
25889   var i0 = 0,
25890       i1 = domain.length - 1,
25891       x0 = domain[i0],
25892       x1 = domain[i1],
25893       t;
25894
25895   if (x1 < x0) {
25896     t = i0, i0 = i1, i1 = t;
25897     t = x0, x0 = x1, x1 = t;
25898   }
25899
25900   domain[i0] = interval.floor(x0);
25901   domain[i1] = interval.ceil(x1);
25902   return domain;
25903 };
25904
25905 function deinterpolate(a, b) {
25906   return (b = Math.log(b / a))
25907       ? function(x) { return Math.log(x / a) / b; }
25908       : constant$4(b);
25909 }
25910
25911 function reinterpolate(a, b) {
25912   return a < 0
25913       ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
25914       : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
25915 }
25916
25917 function pow10(x) {
25918   return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
25919 }
25920
25921 function powp(base) {
25922   return base === 10 ? pow10
25923       : base === Math.E ? Math.exp
25924       : function(x) { return Math.pow(base, x); };
25925 }
25926
25927 function logp(base) {
25928   return base === Math.E ? Math.log
25929       : base === 10 && Math.log10
25930       || base === 2 && Math.log2
25931       || (base = Math.log(base), function(x) { return Math.log(x) / base; });
25932 }
25933
25934 function reflect(f) {
25935   return function(x) {
25936     return -f(-x);
25937   };
25938 }
25939
25940 function log() {
25941   var scale = continuous(deinterpolate, reinterpolate).domain([1, 10]),
25942       domain = scale.domain,
25943       base = 10,
25944       logs = logp(10),
25945       pows = powp(10);
25946
25947   function rescale() {
25948     logs = logp(base), pows = powp(base);
25949     if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
25950     return scale;
25951   }
25952
25953   scale.base = function(_) {
25954     return arguments.length ? (base = +_, rescale()) : base;
25955   };
25956
25957   scale.domain = function(_) {
25958     return arguments.length ? (domain(_), rescale()) : domain();
25959   };
25960
25961   scale.ticks = function(count) {
25962     var d = domain(),
25963         u = d[0],
25964         v = d[d.length - 1],
25965         r;
25966
25967     if (r = v < u) i = u, u = v, v = i;
25968
25969     var i = logs(u),
25970         j = logs(v),
25971         p,
25972         k,
25973         t,
25974         n = count == null ? 10 : +count,
25975         z = [];
25976
25977     if (!(base % 1) && j - i < n) {
25978       i = Math.round(i) - 1, j = Math.round(j) + 1;
25979       if (u > 0) for (; i < j; ++i) {
25980         for (k = 1, p = pows(i); k < base; ++k) {
25981           t = p * k;
25982           if (t < u) continue;
25983           if (t > v) break;
25984           z.push(t);
25985         }
25986       } else for (; i < j; ++i) {
25987         for (k = base - 1, p = pows(i); k >= 1; --k) {
25988           t = p * k;
25989           if (t < u) continue;
25990           if (t > v) break;
25991           z.push(t);
25992         }
25993       }
25994     } else {
25995       z = ticks(i, j, Math.min(j - i, n)).map(pows);
25996     }
25997
25998     return r ? z.reverse() : z;
25999   };
26000
26001   scale.tickFormat = function(count, specifier) {
26002     if (specifier == null) specifier = base === 10 ? ".0e" : ",";
26003     if (typeof specifier !== "function") specifier = format(specifier);
26004     if (count === Infinity) return specifier;
26005     if (count == null) count = 10;
26006     var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
26007     return function(d) {
26008       var i = d / pows(Math.round(logs(d)));
26009       if (i * base < base - 0.5) i *= base;
26010       return i <= k ? specifier(d) : "";
26011     };
26012   };
26013
26014   scale.nice = function() {
26015     return domain(nice(domain(), {
26016       floor: function(x) { return pows(Math.floor(logs(x))); },
26017       ceil: function(x) { return pows(Math.ceil(logs(x))); }
26018     }));
26019   };
26020
26021   scale.copy = function() {
26022     return copy(scale, log().base(base));
26023   };
26024
26025   return scale;
26026 }
26027
26028 function raise(x, exponent) {
26029   return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
26030 }
26031
26032 function pow() {
26033   var exponent = 1,
26034       scale = continuous(deinterpolate, reinterpolate),
26035       domain = scale.domain;
26036
26037   function deinterpolate(a, b) {
26038     return (b = raise(b, exponent) - (a = raise(a, exponent)))
26039         ? function(x) { return (raise(x, exponent) - a) / b; }
26040         : constant$4(b);
26041   }
26042
26043   function reinterpolate(a, b) {
26044     b = raise(b, exponent) - (a = raise(a, exponent));
26045     return function(t) { return raise(a + b * t, 1 / exponent); };
26046   }
26047
26048   scale.exponent = function(_) {
26049     return arguments.length ? (exponent = +_, domain(domain())) : exponent;
26050   };
26051
26052   scale.copy = function() {
26053     return copy(scale, pow().exponent(exponent));
26054   };
26055
26056   return linearish(scale);
26057 }
26058
26059 function sqrt() {
26060   return pow().exponent(0.5);
26061 }
26062
26063 function quantile$$1() {
26064   var domain = [],
26065       range$$1 = [],
26066       thresholds = [];
26067
26068   function rescale() {
26069     var i = 0, n = Math.max(1, range$$1.length);
26070     thresholds = new Array(n - 1);
26071     while (++i < n) thresholds[i - 1] = threshold(domain, i / n);
26072     return scale;
26073   }
26074
26075   function scale(x) {
26076     if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)];
26077   }
26078
26079   scale.invertExtent = function(y) {
26080     var i = range$$1.indexOf(y);
26081     return i < 0 ? [NaN, NaN] : [
26082       i > 0 ? thresholds[i - 1] : domain[0],
26083       i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
26084     ];
26085   };
26086
26087   scale.domain = function(_) {
26088     if (!arguments.length) return domain.slice();
26089     domain = [];
26090     for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
26091     domain.sort(ascending);
26092     return rescale();
26093   };
26094
26095   scale.range = function(_) {
26096     return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice();
26097   };
26098
26099   scale.quantiles = function() {
26100     return thresholds.slice();
26101   };
26102
26103   scale.copy = function() {
26104     return quantile$$1()
26105         .domain(domain)
26106         .range(range$$1);
26107   };
26108
26109   return scale;
26110 }
26111
26112 function quantize$1() {
26113   var x0 = 0,
26114       x1 = 1,
26115       n = 1,
26116       domain = [0.5],
26117       range$$1 = [0, 1];
26118
26119   function scale(x) {
26120     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
26121   }
26122
26123   function rescale() {
26124     var i = -1;
26125     domain = new Array(n);
26126     while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
26127     return scale;
26128   }
26129
26130   scale.domain = function(_) {
26131     return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
26132   };
26133
26134   scale.range = function(_) {
26135     return arguments.length ? (n = (range$$1 = slice$3.call(_)).length - 1, rescale()) : range$$1.slice();
26136   };
26137
26138   scale.invertExtent = function(y) {
26139     var i = range$$1.indexOf(y);
26140     return i < 0 ? [NaN, NaN]
26141         : i < 1 ? [x0, domain[0]]
26142         : i >= n ? [domain[n - 1], x1]
26143         : [domain[i - 1], domain[i]];
26144   };
26145
26146   scale.copy = function() {
26147     return quantize$1()
26148         .domain([x0, x1])
26149         .range(range$$1);
26150   };
26151
26152   return linearish(scale);
26153 }
26154
26155 function threshold$1() {
26156   var domain = [0.5],
26157       range$$1 = [0, 1],
26158       n = 1;
26159
26160   function scale(x) {
26161     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
26162   }
26163
26164   scale.domain = function(_) {
26165     return arguments.length ? (domain = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice();
26166   };
26167
26168   scale.range = function(_) {
26169     return arguments.length ? (range$$1 = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice();
26170   };
26171
26172   scale.invertExtent = function(y) {
26173     var i = range$$1.indexOf(y);
26174     return [domain[i - 1], domain[i]];
26175   };
26176
26177   scale.copy = function() {
26178     return threshold$1()
26179         .domain(domain)
26180         .range(range$$1);
26181   };
26182
26183   return scale;
26184 }
26185
26186 var durationSecond$1 = 1000;
26187 var durationMinute$1 = durationSecond$1 * 60;
26188 var durationHour$1 = durationMinute$1 * 60;
26189 var durationDay$1 = durationHour$1 * 24;
26190 var durationWeek$1 = durationDay$1 * 7;
26191 var durationMonth = durationDay$1 * 30;
26192 var durationYear = durationDay$1 * 365;
26193
26194 function date$1(t) {
26195   return new Date(t);
26196 }
26197
26198 function number$2(t) {
26199   return t instanceof Date ? +t : +new Date(+t);
26200 }
26201
26202 function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) {
26203   var scale = continuous(deinterpolateLinear, interpolateNumber),
26204       invert = scale.invert,
26205       domain = scale.domain;
26206
26207   var formatMillisecond = format(".%L"),
26208       formatSecond = format(":%S"),
26209       formatMinute = format("%I:%M"),
26210       formatHour = format("%I %p"),
26211       formatDay = format("%a %d"),
26212       formatWeek = format("%b %d"),
26213       formatMonth = format("%B"),
26214       formatYear = format("%Y");
26215
26216   var tickIntervals = [
26217     [second$$1,  1,      durationSecond$1],
26218     [second$$1,  5,  5 * durationSecond$1],
26219     [second$$1, 15, 15 * durationSecond$1],
26220     [second$$1, 30, 30 * durationSecond$1],
26221     [minute$$1,  1,      durationMinute$1],
26222     [minute$$1,  5,  5 * durationMinute$1],
26223     [minute$$1, 15, 15 * durationMinute$1],
26224     [minute$$1, 30, 30 * durationMinute$1],
26225     [  hour$$1,  1,      durationHour$1  ],
26226     [  hour$$1,  3,  3 * durationHour$1  ],
26227     [  hour$$1,  6,  6 * durationHour$1  ],
26228     [  hour$$1, 12, 12 * durationHour$1  ],
26229     [   day$$1,  1,      durationDay$1   ],
26230     [   day$$1,  2,  2 * durationDay$1   ],
26231     [  week,  1,      durationWeek$1  ],
26232     [ month$$1,  1,      durationMonth ],
26233     [ month$$1,  3,  3 * durationMonth ],
26234     [  year$$1,  1,      durationYear  ]
26235   ];
26236
26237   function tickFormat(date) {
26238     return (second$$1(date) < date ? formatMillisecond
26239         : minute$$1(date) < date ? formatSecond
26240         : hour$$1(date) < date ? formatMinute
26241         : day$$1(date) < date ? formatHour
26242         : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek)
26243         : year$$1(date) < date ? formatMonth
26244         : formatYear)(date);
26245   }
26246
26247   function tickInterval(interval, start, stop, step) {
26248     if (interval == null) interval = 10;
26249
26250     // If a desired tick count is specified, pick a reasonable tick interval
26251     // based on the extent of the domain and a rough estimate of tick size.
26252     // Otherwise, assume interval is already a time interval and use it.
26253     if (typeof interval === "number") {
26254       var target = Math.abs(stop - start) / interval,
26255           i = bisector(function(i) { return i[2]; }).right(tickIntervals, target);
26256       if (i === tickIntervals.length) {
26257         step = tickStep(start / durationYear, stop / durationYear, interval);
26258         interval = year$$1;
26259       } else if (i) {
26260         i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
26261         step = i[1];
26262         interval = i[0];
26263       } else {
26264         step = tickStep(start, stop, interval);
26265         interval = millisecond$$1;
26266       }
26267     }
26268
26269     return step == null ? interval : interval.every(step);
26270   }
26271
26272   scale.invert = function(y) {
26273     return new Date(invert(y));
26274   };
26275
26276   scale.domain = function(_) {
26277     return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1);
26278   };
26279
26280   scale.ticks = function(interval, step) {
26281     var d = domain(),
26282         t0 = d[0],
26283         t1 = d[d.length - 1],
26284         r = t1 < t0,
26285         t;
26286     if (r) t = t0, t0 = t1, t1 = t;
26287     t = tickInterval(interval, t0, t1, step);
26288     t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
26289     return r ? t.reverse() : t;
26290   };
26291
26292   scale.tickFormat = function(count, specifier) {
26293     return specifier == null ? tickFormat : format(specifier);
26294   };
26295
26296   scale.nice = function(interval, step) {
26297     var d = domain();
26298     return (interval = tickInterval(interval, d[0], d[d.length - 1], step))
26299         ? domain(nice(d, interval))
26300         : scale;
26301   };
26302
26303   scale.copy = function() {
26304     return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format));
26305   };
26306
26307   return scale;
26308 }
26309
26310 var time = function() {
26311   return calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
26312 };
26313
26314 var utcTime = function() {
26315   return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
26316 };
26317
26318 var colors = function(s) {
26319   return s.match(/.{6}/g).map(function(x) {
26320     return "#" + x;
26321   });
26322 };
26323
26324 var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
26325
26326 var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
26327
26328 var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
26329
26330 var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
26331
26332 var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0));
26333
26334 var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
26335
26336 var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
26337
26338 var rainbow = cubehelix();
26339
26340 var rainbow$1 = function(t) {
26341   if (t < 0 || t > 1) t -= Math.floor(t);
26342   var ts = Math.abs(t - 0.5);
26343   rainbow.h = 360 * t - 100;
26344   rainbow.s = 1.5 - 1.5 * ts;
26345   rainbow.l = 0.8 - 0.9 * ts;
26346   return rainbow + "";
26347 };
26348
26349 function ramp(range) {
26350   var n = range.length;
26351   return function(t) {
26352     return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
26353   };
26354 }
26355
26356 var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
26357
26358 var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf"));
26359
26360 var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4"));
26361
26362 var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
26363
26364 function sequential(interpolator) {
26365   var x0 = 0,
26366       x1 = 1,
26367       clamp = false;
26368
26369   function scale(x) {
26370     var t = (x - x0) / (x1 - x0);
26371     return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t);
26372   }
26373
26374   scale.domain = function(_) {
26375     return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
26376   };
26377
26378   scale.clamp = function(_) {
26379     return arguments.length ? (clamp = !!_, scale) : clamp;
26380   };
26381
26382   scale.interpolator = function(_) {
26383     return arguments.length ? (interpolator = _, scale) : interpolator;
26384   };
26385
26386   scale.copy = function() {
26387     return sequential(interpolator).domain([x0, x1]).clamp(clamp);
26388   };
26389
26390   return linearish(scale);
26391 }
26392
26393 var xhtml = "http://www.w3.org/1999/xhtml";
26394
26395 var namespaces = {
26396   svg: "http://www.w3.org/2000/svg",
26397   xhtml: xhtml,
26398   xlink: "http://www.w3.org/1999/xlink",
26399   xml: "http://www.w3.org/XML/1998/namespace",
26400   xmlns: "http://www.w3.org/2000/xmlns/"
26401 };
26402
26403 var namespace = function(name) {
26404   var prefix = name += "", i = prefix.indexOf(":");
26405   if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
26406   return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
26407 };
26408
26409 function creatorInherit(name) {
26410   return function() {
26411     var document = this.ownerDocument,
26412         uri = this.namespaceURI;
26413     return uri === xhtml && document.documentElement.namespaceURI === xhtml
26414         ? document.createElement(name)
26415         : document.createElementNS(uri, name);
26416   };
26417 }
26418
26419 function creatorFixed(fullname) {
26420   return function() {
26421     return this.ownerDocument.createElementNS(fullname.space, fullname.local);
26422   };
26423 }
26424
26425 var creator = function(name) {
26426   var fullname = namespace(name);
26427   return (fullname.local
26428       ? creatorFixed
26429       : creatorInherit)(fullname);
26430 };
26431
26432 var nextId = 0;
26433
26434 function local() {
26435   return new Local;
26436 }
26437
26438 function Local() {
26439   this._ = "@" + (++nextId).toString(36);
26440 }
26441
26442 Local.prototype = local.prototype = {
26443   constructor: Local,
26444   get: function(node) {
26445     var id = this._;
26446     while (!(id in node)) if (!(node = node.parentNode)) return;
26447     return node[id];
26448   },
26449   set: function(node, value) {
26450     return node[this._] = value;
26451   },
26452   remove: function(node) {
26453     return this._ in node && delete node[this._];
26454   },
26455   toString: function() {
26456     return this._;
26457   }
26458 };
26459
26460 var matcher = function(selector) {
26461   return function() {
26462     return this.matches(selector);
26463   };
26464 };
26465
26466 if (typeof document !== "undefined") {
26467   var element = document.documentElement;
26468   if (!element.matches) {
26469     var vendorMatches = element.webkitMatchesSelector
26470         || element.msMatchesSelector
26471         || element.mozMatchesSelector
26472         || element.oMatchesSelector;
26473     matcher = function(selector) {
26474       return function() {
26475         return vendorMatches.call(this, selector);
26476       };
26477     };
26478   }
26479 }
26480
26481 var matcher$1 = matcher;
26482
26483 var filterEvents = {};
26484
26485 var event = null;
26486
26487 if (typeof document !== "undefined") {
26488   var element$1 = document.documentElement;
26489   if (!("onmouseenter" in element$1)) {
26490     filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
26491   }
26492 }
26493
26494 function filterContextListener(listener, index, group) {
26495   listener = contextListener(listener, index, group);
26496   return function(event) {
26497     var related = event.relatedTarget;
26498     if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
26499       listener.call(this, event);
26500     }
26501   };
26502 }
26503
26504 function contextListener(listener, index, group) {
26505   return function(event1) {
26506     var event0 = event; // Events can be reentrant (e.g., focus).
26507     event = event1;
26508     try {
26509       listener.call(this, this.__data__, index, group);
26510     } finally {
26511       event = event0;
26512     }
26513   };
26514 }
26515
26516 function parseTypenames$1(typenames) {
26517   return typenames.trim().split(/^|\s+/).map(function(t) {
26518     var name = "", i = t.indexOf(".");
26519     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
26520     return {type: t, name: name};
26521   });
26522 }
26523
26524 function onRemove(typename) {
26525   return function() {
26526     var on = this.__on;
26527     if (!on) return;
26528     for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
26529       if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
26530         this.removeEventListener(o.type, o.listener, o.capture);
26531       } else {
26532         on[++i] = o;
26533       }
26534     }
26535     if (++i) on.length = i;
26536     else delete this.__on;
26537   };
26538 }
26539
26540 function onAdd(typename, value, capture) {
26541   var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
26542   return function(d, i, group) {
26543     var on = this.__on, o, listener = wrap(value, i, group);
26544     if (on) for (var j = 0, m = on.length; j < m; ++j) {
26545       if ((o = on[j]).type === typename.type && o.name === typename.name) {
26546         this.removeEventListener(o.type, o.listener, o.capture);
26547         this.addEventListener(o.type, o.listener = listener, o.capture = capture);
26548         o.value = value;
26549         return;
26550       }
26551     }
26552     this.addEventListener(typename.type, listener, capture);
26553     o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
26554     if (!on) this.__on = [o];
26555     else on.push(o);
26556   };
26557 }
26558
26559 var selection_on = function(typename, value, capture) {
26560   var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
26561
26562   if (arguments.length < 2) {
26563     var on = this.node().__on;
26564     if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
26565       for (i = 0, o = on[j]; i < n; ++i) {
26566         if ((t = typenames[i]).type === o.type && t.name === o.name) {
26567           return o.value;
26568         }
26569       }
26570     }
26571     return;
26572   }
26573
26574   on = value ? onAdd : onRemove;
26575   if (capture == null) capture = false;
26576   for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
26577   return this;
26578 };
26579
26580 function customEvent(event1, listener, that, args) {
26581   var event0 = event;
26582   event1.sourceEvent = event;
26583   event = event1;
26584   try {
26585     return listener.apply(that, args);
26586   } finally {
26587     event = event0;
26588   }
26589 }
26590
26591 var sourceEvent = function() {
26592   var current = event, source;
26593   while (source = current.sourceEvent) current = source;
26594   return current;
26595 };
26596
26597 var point$5 = function(node, event) {
26598   var svg = node.ownerSVGElement || node;
26599
26600   if (svg.createSVGPoint) {
26601     var point = svg.createSVGPoint();
26602     point.x = event.clientX, point.y = event.clientY;
26603     point = point.matrixTransform(node.getScreenCTM().inverse());
26604     return [point.x, point.y];
26605   }
26606
26607   var rect = node.getBoundingClientRect();
26608   return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
26609 };
26610
26611 var mouse = function(node) {
26612   var event = sourceEvent();
26613   if (event.changedTouches) event = event.changedTouches[0];
26614   return point$5(node, event);
26615 };
26616
26617 function none$2() {}
26618
26619 var selector = function(selector) {
26620   return selector == null ? none$2 : function() {
26621     return this.querySelector(selector);
26622   };
26623 };
26624
26625 var selection_select = function(select) {
26626   if (typeof select !== "function") select = selector(select);
26627
26628   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
26629     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
26630       if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
26631         if ("__data__" in node) subnode.__data__ = node.__data__;
26632         subgroup[i] = subnode;
26633       }
26634     }
26635   }
26636
26637   return new Selection(subgroups, this._parents);
26638 };
26639
26640 function empty() {
26641   return [];
26642 }
26643
26644 var selectorAll = function(selector) {
26645   return selector == null ? empty : function() {
26646     return this.querySelectorAll(selector);
26647   };
26648 };
26649
26650 var selection_selectAll = function(select) {
26651   if (typeof select !== "function") select = selectorAll(select);
26652
26653   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
26654     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
26655       if (node = group[i]) {
26656         subgroups.push(select.call(node, node.__data__, i, group));
26657         parents.push(node);
26658       }
26659     }
26660   }
26661
26662   return new Selection(subgroups, parents);
26663 };
26664
26665 var selection_filter = function(match) {
26666   if (typeof match !== "function") match = matcher$1(match);
26667
26668   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
26669     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
26670       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
26671         subgroup.push(node);
26672       }
26673     }
26674   }
26675
26676   return new Selection(subgroups, this._parents);
26677 };
26678
26679 var sparse = function(update) {
26680   return new Array(update.length);
26681 };
26682
26683 var selection_enter = function() {
26684   return new Selection(this._enter || this._groups.map(sparse), this._parents);
26685 };
26686
26687 function EnterNode(parent, datum) {
26688   this.ownerDocument = parent.ownerDocument;
26689   this.namespaceURI = parent.namespaceURI;
26690   this._next = null;
26691   this._parent = parent;
26692   this.__data__ = datum;
26693 }
26694
26695 EnterNode.prototype = {
26696   constructor: EnterNode,
26697   appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
26698   insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
26699   querySelector: function(selector) { return this._parent.querySelector(selector); },
26700   querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
26701 };
26702
26703 var constant$5 = function(x) {
26704   return function() {
26705     return x;
26706   };
26707 };
26708
26709 var keyPrefix = "$"; // Protect against keys like “__proto__”.
26710
26711 function bindIndex(parent, group, enter, update, exit, data) {
26712   var i = 0,
26713       node,
26714       groupLength = group.length,
26715       dataLength = data.length;
26716
26717   // Put any non-null nodes that fit into update.
26718   // Put any null nodes into enter.
26719   // Put any remaining data into enter.
26720   for (; i < dataLength; ++i) {
26721     if (node = group[i]) {
26722       node.__data__ = data[i];
26723       update[i] = node;
26724     } else {
26725       enter[i] = new EnterNode(parent, data[i]);
26726     }
26727   }
26728
26729   // Put any non-null nodes that don’t fit into exit.
26730   for (; i < groupLength; ++i) {
26731     if (node = group[i]) {
26732       exit[i] = node;
26733     }
26734   }
26735 }
26736
26737 function bindKey(parent, group, enter, update, exit, data, key) {
26738   var i,
26739       node,
26740       nodeByKeyValue = {},
26741       groupLength = group.length,
26742       dataLength = data.length,
26743       keyValues = new Array(groupLength),
26744       keyValue;
26745
26746   // Compute the key for each node.
26747   // If multiple nodes have the same key, the duplicates are added to exit.
26748   for (i = 0; i < groupLength; ++i) {
26749     if (node = group[i]) {
26750       keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
26751       if (keyValue in nodeByKeyValue) {
26752         exit[i] = node;
26753       } else {
26754         nodeByKeyValue[keyValue] = node;
26755       }
26756     }
26757   }
26758
26759   // Compute the key for each datum.
26760   // If there a node associated with this key, join and add it to update.
26761   // If there is not (or the key is a duplicate), add it to enter.
26762   for (i = 0; i < dataLength; ++i) {
26763     keyValue = keyPrefix + key.call(parent, data[i], i, data);
26764     if (node = nodeByKeyValue[keyValue]) {
26765       update[i] = node;
26766       node.__data__ = data[i];
26767       nodeByKeyValue[keyValue] = null;
26768     } else {
26769       enter[i] = new EnterNode(parent, data[i]);
26770     }
26771   }
26772
26773   // Add any remaining nodes that were not bound to data to exit.
26774   for (i = 0; i < groupLength; ++i) {
26775     if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
26776       exit[i] = node;
26777     }
26778   }
26779 }
26780
26781 var selection_data = function(value, key) {
26782   if (!value) {
26783     data = new Array(this.size()), j = -1;
26784     this.each(function(d) { data[++j] = d; });
26785     return data;
26786   }
26787
26788   var bind = key ? bindKey : bindIndex,
26789       parents = this._parents,
26790       groups = this._groups;
26791
26792   if (typeof value !== "function") value = constant$5(value);
26793
26794   for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
26795     var parent = parents[j],
26796         group = groups[j],
26797         groupLength = group.length,
26798         data = value.call(parent, parent && parent.__data__, j, parents),
26799         dataLength = data.length,
26800         enterGroup = enter[j] = new Array(dataLength),
26801         updateGroup = update[j] = new Array(dataLength),
26802         exitGroup = exit[j] = new Array(groupLength);
26803
26804     bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
26805
26806     // Now connect the enter nodes to their following update node, such that
26807     // appendChild can insert the materialized enter node before this node,
26808     // rather than at the end of the parent node.
26809     for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
26810       if (previous = enterGroup[i0]) {
26811         if (i0 >= i1) i1 = i0 + 1;
26812         while (!(next = updateGroup[i1]) && ++i1 < dataLength);
26813         previous._next = next || null;
26814       }
26815     }
26816   }
26817
26818   update = new Selection(update, parents);
26819   update._enter = enter;
26820   update._exit = exit;
26821   return update;
26822 };
26823
26824 var selection_exit = function() {
26825   return new Selection(this._exit || this._groups.map(sparse), this._parents);
26826 };
26827
26828 var selection_merge = function(selection) {
26829
26830   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) {
26831     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
26832       if (node = group0[i] || group1[i]) {
26833         merge[i] = node;
26834       }
26835     }
26836   }
26837
26838   for (; j < m0; ++j) {
26839     merges[j] = groups0[j];
26840   }
26841
26842   return new Selection(merges, this._parents);
26843 };
26844
26845 var selection_order = function() {
26846
26847   for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
26848     for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
26849       if (node = group[i]) {
26850         if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
26851         next = node;
26852       }
26853     }
26854   }
26855
26856   return this;
26857 };
26858
26859 var selection_sort = function(compare) {
26860   if (!compare) compare = ascending$2;
26861
26862   function compareNode(a, b) {
26863     return a && b ? compare(a.__data__, b.__data__) : !a - !b;
26864   }
26865
26866   for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
26867     for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
26868       if (node = group[i]) {
26869         sortgroup[i] = node;
26870       }
26871     }
26872     sortgroup.sort(compareNode);
26873   }
26874
26875   return new Selection(sortgroups, this._parents).order();
26876 };
26877
26878 function ascending$2(a, b) {
26879   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
26880 }
26881
26882 var selection_call = function() {
26883   var callback = arguments[0];
26884   arguments[0] = this;
26885   callback.apply(null, arguments);
26886   return this;
26887 };
26888
26889 var selection_nodes = function() {
26890   var nodes = new Array(this.size()), i = -1;
26891   this.each(function() { nodes[++i] = this; });
26892   return nodes;
26893 };
26894
26895 var selection_node = function() {
26896
26897   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
26898     for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
26899       var node = group[i];
26900       if (node) return node;
26901     }
26902   }
26903
26904   return null;
26905 };
26906
26907 var selection_size = function() {
26908   var size = 0;
26909   this.each(function() { ++size; });
26910   return size;
26911 };
26912
26913 var selection_empty = function() {
26914   return !this.node();
26915 };
26916
26917 var selection_each = function(callback) {
26918
26919   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
26920     for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
26921       if (node = group[i]) callback.call(node, node.__data__, i, group);
26922     }
26923   }
26924
26925   return this;
26926 };
26927
26928 function attrRemove(name) {
26929   return function() {
26930     this.removeAttribute(name);
26931   };
26932 }
26933
26934 function attrRemoveNS(fullname) {
26935   return function() {
26936     this.removeAttributeNS(fullname.space, fullname.local);
26937   };
26938 }
26939
26940 function attrConstant(name, value) {
26941   return function() {
26942     this.setAttribute(name, value);
26943   };
26944 }
26945
26946 function attrConstantNS(fullname, value) {
26947   return function() {
26948     this.setAttributeNS(fullname.space, fullname.local, value);
26949   };
26950 }
26951
26952 function attrFunction(name, value) {
26953   return function() {
26954     var v = value.apply(this, arguments);
26955     if (v == null) this.removeAttribute(name);
26956     else this.setAttribute(name, v);
26957   };
26958 }
26959
26960 function attrFunctionNS(fullname, value) {
26961   return function() {
26962     var v = value.apply(this, arguments);
26963     if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
26964     else this.setAttributeNS(fullname.space, fullname.local, v);
26965   };
26966 }
26967
26968 var selection_attr = function(name, value) {
26969   var fullname = namespace(name);
26970
26971   if (arguments.length < 2) {
26972     var node = this.node();
26973     return fullname.local
26974         ? node.getAttributeNS(fullname.space, fullname.local)
26975         : node.getAttribute(fullname);
26976   }
26977
26978   return this.each((value == null
26979       ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
26980       ? (fullname.local ? attrFunctionNS : attrFunction)
26981       : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
26982 };
26983
26984 var window$1 = function(node) {
26985   return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
26986       || (node.document && node) // node is a Window
26987       || node.defaultView; // node is a Document
26988 };
26989
26990 function styleRemove(name) {
26991   return function() {
26992     this.style.removeProperty(name);
26993   };
26994 }
26995
26996 function styleConstant(name, value, priority) {
26997   return function() {
26998     this.style.setProperty(name, value, priority);
26999   };
27000 }
27001
27002 function styleFunction(name, value, priority) {
27003   return function() {
27004     var v = value.apply(this, arguments);
27005     if (v == null) this.style.removeProperty(name);
27006     else this.style.setProperty(name, v, priority);
27007   };
27008 }
27009
27010 var selection_style = function(name, value, priority) {
27011   var node;
27012   return arguments.length > 1
27013       ? this.each((value == null
27014             ? styleRemove : typeof value === "function"
27015             ? styleFunction
27016             : styleConstant)(name, value, priority == null ? "" : priority))
27017       : window$1(node = this.node())
27018           .getComputedStyle(node, null)
27019           .getPropertyValue(name);
27020 };
27021
27022 function propertyRemove(name) {
27023   return function() {
27024     delete this[name];
27025   };
27026 }
27027
27028 function propertyConstant(name, value) {
27029   return function() {
27030     this[name] = value;
27031   };
27032 }
27033
27034 function propertyFunction(name, value) {
27035   return function() {
27036     var v = value.apply(this, arguments);
27037     if (v == null) delete this[name];
27038     else this[name] = v;
27039   };
27040 }
27041
27042 var selection_property = function(name, value) {
27043   return arguments.length > 1
27044       ? this.each((value == null
27045           ? propertyRemove : typeof value === "function"
27046           ? propertyFunction
27047           : propertyConstant)(name, value))
27048       : this.node()[name];
27049 };
27050
27051 function classArray(string) {
27052   return string.trim().split(/^|\s+/);
27053 }
27054
27055 function classList(node) {
27056   return node.classList || new ClassList(node);
27057 }
27058
27059 function ClassList(node) {
27060   this._node = node;
27061   this._names = classArray(node.getAttribute("class") || "");
27062 }
27063
27064 ClassList.prototype = {
27065   add: function(name) {
27066     var i = this._names.indexOf(name);
27067     if (i < 0) {
27068       this._names.push(name);
27069       this._node.setAttribute("class", this._names.join(" "));
27070     }
27071   },
27072   remove: function(name) {
27073     var i = this._names.indexOf(name);
27074     if (i >= 0) {
27075       this._names.splice(i, 1);
27076       this._node.setAttribute("class", this._names.join(" "));
27077     }
27078   },
27079   contains: function(name) {
27080     return this._names.indexOf(name) >= 0;
27081   }
27082 };
27083
27084 function classedAdd(node, names) {
27085   var list = classList(node), i = -1, n = names.length;
27086   while (++i < n) list.add(names[i]);
27087 }
27088
27089 function classedRemove(node, names) {
27090   var list = classList(node), i = -1, n = names.length;
27091   while (++i < n) list.remove(names[i]);
27092 }
27093
27094 function classedTrue(names) {
27095   return function() {
27096     classedAdd(this, names);
27097   };
27098 }
27099
27100 function classedFalse(names) {
27101   return function() {
27102     classedRemove(this, names);
27103   };
27104 }
27105
27106 function classedFunction(names, value) {
27107   return function() {
27108     (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
27109   };
27110 }
27111
27112 var selection_classed = function(name, value) {
27113   var names = classArray(name + "");
27114
27115   if (arguments.length < 2) {
27116     var list = classList(this.node()), i = -1, n = names.length;
27117     while (++i < n) if (!list.contains(names[i])) return false;
27118     return true;
27119   }
27120
27121   return this.each((typeof value === "function"
27122       ? classedFunction : value
27123       ? classedTrue
27124       : classedFalse)(names, value));
27125 };
27126
27127 function textRemove() {
27128   this.textContent = "";
27129 }
27130
27131 function textConstant(value) {
27132   return function() {
27133     this.textContent = value;
27134   };
27135 }
27136
27137 function textFunction(value) {
27138   return function() {
27139     var v = value.apply(this, arguments);
27140     this.textContent = v == null ? "" : v;
27141   };
27142 }
27143
27144 var selection_text = function(value) {
27145   return arguments.length
27146       ? this.each(value == null
27147           ? textRemove : (typeof value === "function"
27148           ? textFunction
27149           : textConstant)(value))
27150       : this.node().textContent;
27151 };
27152
27153 function htmlRemove() {
27154   this.innerHTML = "";
27155 }
27156
27157 function htmlConstant(value) {
27158   return function() {
27159     this.innerHTML = value;
27160   };
27161 }
27162
27163 function htmlFunction(value) {
27164   return function() {
27165     var v = value.apply(this, arguments);
27166     this.innerHTML = v == null ? "" : v;
27167   };
27168 }
27169
27170 var selection_html = function(value) {
27171   return arguments.length
27172       ? this.each(value == null
27173           ? htmlRemove : (typeof value === "function"
27174           ? htmlFunction
27175           : htmlConstant)(value))
27176       : this.node().innerHTML;
27177 };
27178
27179 function raise$1() {
27180   if (this.nextSibling) this.parentNode.appendChild(this);
27181 }
27182
27183 var selection_raise = function() {
27184   return this.each(raise$1);
27185 };
27186
27187 function lower() {
27188   if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
27189 }
27190
27191 var selection_lower = function() {
27192   return this.each(lower);
27193 };
27194
27195 var selection_append = function(name) {
27196   var create = typeof name === "function" ? name : creator(name);
27197   return this.select(function() {
27198     return this.appendChild(create.apply(this, arguments));
27199   });
27200 };
27201
27202 function constantNull() {
27203   return null;
27204 }
27205
27206 var selection_insert = function(name, before) {
27207   var create = typeof name === "function" ? name : creator(name),
27208       select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
27209   return this.select(function() {
27210     return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
27211   });
27212 };
27213
27214 function remove() {
27215   var parent = this.parentNode;
27216   if (parent) parent.removeChild(this);
27217 }
27218
27219 var selection_remove = function() {
27220   return this.each(remove);
27221 };
27222
27223 var selection_datum = function(value) {
27224   return arguments.length
27225       ? this.property("__data__", value)
27226       : this.node().__data__;
27227 };
27228
27229 function dispatchEvent(node, type, params) {
27230   var window = window$1(node),
27231       event = window.CustomEvent;
27232
27233   if (event) {
27234     event = new event(type, params);
27235   } else {
27236     event = window.document.createEvent("Event");
27237     if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
27238     else event.initEvent(type, false, false);
27239   }
27240
27241   node.dispatchEvent(event);
27242 }
27243
27244 function dispatchConstant(type, params) {
27245   return function() {
27246     return dispatchEvent(this, type, params);
27247   };
27248 }
27249
27250 function dispatchFunction(type, params) {
27251   return function() {
27252     return dispatchEvent(this, type, params.apply(this, arguments));
27253   };
27254 }
27255
27256 var selection_dispatch = function(type, params) {
27257   return this.each((typeof params === "function"
27258       ? dispatchFunction
27259       : dispatchConstant)(type, params));
27260 };
27261
27262 var root = [null];
27263
27264 function Selection(groups, parents) {
27265   this._groups = groups;
27266   this._parents = parents;
27267 }
27268
27269 function selection() {
27270   return new Selection([[document.documentElement]], root);
27271 }
27272
27273 Selection.prototype = selection.prototype = {
27274   constructor: Selection,
27275   select: selection_select,
27276   selectAll: selection_selectAll,
27277   filter: selection_filter,
27278   data: selection_data,
27279   enter: selection_enter,
27280   exit: selection_exit,
27281   merge: selection_merge,
27282   order: selection_order,
27283   sort: selection_sort,
27284   call: selection_call,
27285   nodes: selection_nodes,
27286   node: selection_node,
27287   size: selection_size,
27288   empty: selection_empty,
27289   each: selection_each,
27290   attr: selection_attr,
27291   style: selection_style,
27292   property: selection_property,
27293   classed: selection_classed,
27294   text: selection_text,
27295   html: selection_html,
27296   raise: selection_raise,
27297   lower: selection_lower,
27298   append: selection_append,
27299   insert: selection_insert,
27300   remove: selection_remove,
27301   datum: selection_datum,
27302   on: selection_on,
27303   dispatch: selection_dispatch
27304 };
27305
27306 var select = function(selector) {
27307   return typeof selector === "string"
27308       ? new Selection([[document.querySelector(selector)]], [document.documentElement])
27309       : new Selection([[selector]], root);
27310 };
27311
27312 var selectAll = function(selector) {
27313   return typeof selector === "string"
27314       ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
27315       : new Selection([selector == null ? [] : selector], root);
27316 };
27317
27318 var touch = function(node, touches, identifier) {
27319   if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
27320
27321   for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
27322     if ((touch = touches[i]).identifier === identifier) {
27323       return point$5(node, touch);
27324     }
27325   }
27326
27327   return null;
27328 };
27329
27330 var touches = function(node, touches) {
27331   if (touches == null) touches = sourceEvent().touches;
27332
27333   for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
27334     points[i] = point$5(node, touches[i]);
27335   }
27336
27337   return points;
27338 };
27339
27340 var emptyOn = dispatch("start", "end", "interrupt");
27341 var emptyTween = [];
27342
27343 var CREATED = 0;
27344 var SCHEDULED = 1;
27345 var STARTING = 2;
27346 var STARTED = 3;
27347 var RUNNING = 4;
27348 var ENDING = 5;
27349 var ENDED = 6;
27350
27351 var schedule = function(node, name, id, index, group, timing) {
27352   var schedules = node.__transition;
27353   if (!schedules) node.__transition = {};
27354   else if (id in schedules) return;
27355   create(node, id, {
27356     name: name,
27357     index: index, // For context during callback.
27358     group: group, // For context during callback.
27359     on: emptyOn,
27360     tween: emptyTween,
27361     time: timing.time,
27362     delay: timing.delay,
27363     duration: timing.duration,
27364     ease: timing.ease,
27365     timer: null,
27366     state: CREATED
27367   });
27368 };
27369
27370 function init(node, id) {
27371   var schedule = node.__transition;
27372   if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late");
27373   return schedule;
27374 }
27375
27376 function set$3(node, id) {
27377   var schedule = node.__transition;
27378   if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late");
27379   return schedule;
27380 }
27381
27382 function get$1(node, id) {
27383   var schedule = node.__transition;
27384   if (!schedule || !(schedule = schedule[id])) throw new Error("too late");
27385   return schedule;
27386 }
27387
27388 function create(node, id, self) {
27389   var schedules = node.__transition,
27390       tween;
27391
27392   // Initialize the self timer when the transition is created.
27393   // Note the actual delay is not known until the first callback!
27394   schedules[id] = self;
27395   self.timer = timer(schedule, 0, self.time);
27396
27397   function schedule(elapsed) {
27398     self.state = SCHEDULED;
27399     self.timer.restart(start, self.delay, self.time);
27400
27401     // If the elapsed delay is less than our first sleep, start immediately.
27402     if (self.delay <= elapsed) start(elapsed - self.delay);
27403   }
27404
27405   function start(elapsed) {
27406     var i, j, n, o;
27407
27408     // If the state is not SCHEDULED, then we previously errored on start.
27409     if (self.state !== SCHEDULED) return stop();
27410
27411     for (i in schedules) {
27412       o = schedules[i];
27413       if (o.name !== self.name) continue;
27414
27415       // While this element already has a starting transition during this frame,
27416       // defer starting an interrupting transition until that transition has a
27417       // chance to tick (and possibly end); see d3/d3-transition#54!
27418       if (o.state === STARTED) return timeout$1(start);
27419
27420       // Interrupt the active transition, if any.
27421       // Dispatch the interrupt event.
27422       if (o.state === RUNNING) {
27423         o.state = ENDED;
27424         o.timer.stop();
27425         o.on.call("interrupt", node, node.__data__, o.index, o.group);
27426         delete schedules[i];
27427       }
27428
27429       // Cancel any pre-empted transitions. No interrupt event is dispatched
27430       // because the cancelled transitions never started. Note that this also
27431       // removes this transition from the pending list!
27432       else if (+i < id) {
27433         o.state = ENDED;
27434         o.timer.stop();
27435         delete schedules[i];
27436       }
27437     }
27438
27439     // Defer the first tick to end of the current frame; see d3/d3#1576.
27440     // Note the transition may be canceled after start and before the first tick!
27441     // Note this must be scheduled before the start event; see d3/d3-transition#16!
27442     // Assuming this is successful, subsequent callbacks go straight to tick.
27443     timeout$1(function() {
27444       if (self.state === STARTED) {
27445         self.state = RUNNING;
27446         self.timer.restart(tick, self.delay, self.time);
27447         tick(elapsed);
27448       }
27449     });
27450
27451     // Dispatch the start event.
27452     // Note this must be done before the tween are initialized.
27453     self.state = STARTING;
27454     self.on.call("start", node, node.__data__, self.index, self.group);
27455     if (self.state !== STARTING) return; // interrupted
27456     self.state = STARTED;
27457
27458     // Initialize the tween, deleting null tween.
27459     tween = new Array(n = self.tween.length);
27460     for (i = 0, j = -1; i < n; ++i) {
27461       if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
27462         tween[++j] = o;
27463       }
27464     }
27465     tween.length = j + 1;
27466   }
27467
27468   function tick(elapsed) {
27469     var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
27470         i = -1,
27471         n = tween.length;
27472
27473     while (++i < n) {
27474       tween[i].call(null, t);
27475     }
27476
27477     // Dispatch the end event.
27478     if (self.state === ENDING) {
27479       self.on.call("end", node, node.__data__, self.index, self.group);
27480       stop();
27481     }
27482   }
27483
27484   function stop() {
27485     self.state = ENDED;
27486     self.timer.stop();
27487     delete schedules[id];
27488     for (var i in schedules) return; // eslint-disable-line no-unused-vars
27489     delete node.__transition;
27490   }
27491 }
27492
27493 var interrupt = function(node, name) {
27494   var schedules = node.__transition,
27495       schedule,
27496       active,
27497       empty = true,
27498       i;
27499
27500   if (!schedules) return;
27501
27502   name = name == null ? null : name + "";
27503
27504   for (i in schedules) {
27505     if ((schedule = schedules[i]).name !== name) { empty = false; continue; }
27506     active = schedule.state > STARTING && schedule.state < ENDING;
27507     schedule.state = ENDED;
27508     schedule.timer.stop();
27509     if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group);
27510     delete schedules[i];
27511   }
27512
27513   if (empty) delete node.__transition;
27514 };
27515
27516 var selection_interrupt = function(name) {
27517   return this.each(function() {
27518     interrupt(this, name);
27519   });
27520 };
27521
27522 function tweenRemove(id, name) {
27523   var tween0, tween1;
27524   return function() {
27525     var schedule = set$3(this, id),
27526         tween = schedule.tween;
27527
27528     // If this node shared tween with the previous node,
27529     // just assign the updated shared tween and we’re done!
27530     // Otherwise, copy-on-write.
27531     if (tween !== tween0) {
27532       tween1 = tween0 = tween;
27533       for (var i = 0, n = tween1.length; i < n; ++i) {
27534         if (tween1[i].name === name) {
27535           tween1 = tween1.slice();
27536           tween1.splice(i, 1);
27537           break;
27538         }
27539       }
27540     }
27541
27542     schedule.tween = tween1;
27543   };
27544 }
27545
27546 function tweenFunction(id, name, value) {
27547   var tween0, tween1;
27548   if (typeof value !== "function") throw new Error;
27549   return function() {
27550     var schedule = set$3(this, id),
27551         tween = schedule.tween;
27552
27553     // If this node shared tween with the previous node,
27554     // just assign the updated shared tween and we’re done!
27555     // Otherwise, copy-on-write.
27556     if (tween !== tween0) {
27557       tween1 = (tween0 = tween).slice();
27558       for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) {
27559         if (tween1[i].name === name) {
27560           tween1[i] = t;
27561           break;
27562         }
27563       }
27564       if (i === n) tween1.push(t);
27565     }
27566
27567     schedule.tween = tween1;
27568   };
27569 }
27570
27571 var transition_tween = function(name, value) {
27572   var id = this._id;
27573
27574   name += "";
27575
27576   if (arguments.length < 2) {
27577     var tween = get$1(this.node(), id).tween;
27578     for (var i = 0, n = tween.length, t; i < n; ++i) {
27579       if ((t = tween[i]).name === name) {
27580         return t.value;
27581       }
27582     }
27583     return null;
27584   }
27585
27586   return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
27587 };
27588
27589 function tweenValue(transition, name, value) {
27590   var id = transition._id;
27591
27592   transition.each(function() {
27593     var schedule = set$3(this, id);
27594     (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
27595   });
27596
27597   return function(node) {
27598     return get$1(node, id).value[name];
27599   };
27600 }
27601
27602 var interpolate$1 = function(a, b) {
27603   var c;
27604   return (typeof b === "number" ? interpolateNumber
27605       : b instanceof color ? interpolateRgb
27606       : (c = color(b)) ? (b = c, interpolateRgb)
27607       : interpolateString)(a, b);
27608 };
27609
27610 function attrRemove$1(name) {
27611   return function() {
27612     this.removeAttribute(name);
27613   };
27614 }
27615
27616 function attrRemoveNS$1(fullname) {
27617   return function() {
27618     this.removeAttributeNS(fullname.space, fullname.local);
27619   };
27620 }
27621
27622 function attrConstant$1(name, interpolate$$1, value1) {
27623   var value00,
27624       interpolate0;
27625   return function() {
27626     var value0 = this.getAttribute(name);
27627     return value0 === value1 ? null
27628         : value0 === value00 ? interpolate0
27629         : interpolate0 = interpolate$$1(value00 = value0, value1);
27630   };
27631 }
27632
27633 function attrConstantNS$1(fullname, interpolate$$1, value1) {
27634   var value00,
27635       interpolate0;
27636   return function() {
27637     var value0 = this.getAttributeNS(fullname.space, fullname.local);
27638     return value0 === value1 ? null
27639         : value0 === value00 ? interpolate0
27640         : interpolate0 = interpolate$$1(value00 = value0, value1);
27641   };
27642 }
27643
27644 function attrFunction$1(name, interpolate$$1, value) {
27645   var value00,
27646       value10,
27647       interpolate0;
27648   return function() {
27649     var value0, value1 = value(this);
27650     if (value1 == null) return void this.removeAttribute(name);
27651     value0 = this.getAttribute(name);
27652     return value0 === value1 ? null
27653         : value0 === value00 && value1 === value10 ? interpolate0
27654         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27655   };
27656 }
27657
27658 function attrFunctionNS$1(fullname, interpolate$$1, value) {
27659   var value00,
27660       value10,
27661       interpolate0;
27662   return function() {
27663     var value0, value1 = value(this);
27664     if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
27665     value0 = this.getAttributeNS(fullname.space, fullname.local);
27666     return value0 === value1 ? null
27667         : value0 === value00 && value1 === value10 ? interpolate0
27668         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27669   };
27670 }
27671
27672 var transition_attr = function(name, value) {
27673   var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$1;
27674   return this.attrTween(name, typeof value === "function"
27675       ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value))
27676       : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname)
27677       : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value));
27678 };
27679
27680 function attrTweenNS(fullname, value) {
27681   function tween() {
27682     var node = this, i = value.apply(node, arguments);
27683     return i && function(t) {
27684       node.setAttributeNS(fullname.space, fullname.local, i(t));
27685     };
27686   }
27687   tween._value = value;
27688   return tween;
27689 }
27690
27691 function attrTween(name, value) {
27692   function tween() {
27693     var node = this, i = value.apply(node, arguments);
27694     return i && function(t) {
27695       node.setAttribute(name, i(t));
27696     };
27697   }
27698   tween._value = value;
27699   return tween;
27700 }
27701
27702 var transition_attrTween = function(name, value) {
27703   var key = "attr." + name;
27704   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
27705   if (value == null) return this.tween(key, null);
27706   if (typeof value !== "function") throw new Error;
27707   var fullname = namespace(name);
27708   return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
27709 };
27710
27711 function delayFunction(id, value) {
27712   return function() {
27713     init(this, id).delay = +value.apply(this, arguments);
27714   };
27715 }
27716
27717 function delayConstant(id, value) {
27718   return value = +value, function() {
27719     init(this, id).delay = value;
27720   };
27721 }
27722
27723 var transition_delay = function(value) {
27724   var id = this._id;
27725
27726   return arguments.length
27727       ? this.each((typeof value === "function"
27728           ? delayFunction
27729           : delayConstant)(id, value))
27730       : get$1(this.node(), id).delay;
27731 };
27732
27733 function durationFunction(id, value) {
27734   return function() {
27735     set$3(this, id).duration = +value.apply(this, arguments);
27736   };
27737 }
27738
27739 function durationConstant(id, value) {
27740   return value = +value, function() {
27741     set$3(this, id).duration = value;
27742   };
27743 }
27744
27745 var transition_duration = function(value) {
27746   var id = this._id;
27747
27748   return arguments.length
27749       ? this.each((typeof value === "function"
27750           ? durationFunction
27751           : durationConstant)(id, value))
27752       : get$1(this.node(), id).duration;
27753 };
27754
27755 function easeConstant(id, value) {
27756   if (typeof value !== "function") throw new Error;
27757   return function() {
27758     set$3(this, id).ease = value;
27759   };
27760 }
27761
27762 var transition_ease = function(value) {
27763   var id = this._id;
27764
27765   return arguments.length
27766       ? this.each(easeConstant(id, value))
27767       : get$1(this.node(), id).ease;
27768 };
27769
27770 var transition_filter = function(match) {
27771   if (typeof match !== "function") match = matcher$1(match);
27772
27773   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
27774     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
27775       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
27776         subgroup.push(node);
27777       }
27778     }
27779   }
27780
27781   return new Transition(subgroups, this._parents, this._name, this._id);
27782 };
27783
27784 var transition_merge = function(transition) {
27785   if (transition._id !== this._id) throw new Error;
27786
27787   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) {
27788     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
27789       if (node = group0[i] || group1[i]) {
27790         merge[i] = node;
27791       }
27792     }
27793   }
27794
27795   for (; j < m0; ++j) {
27796     merges[j] = groups0[j];
27797   }
27798
27799   return new Transition(merges, this._parents, this._name, this._id);
27800 };
27801
27802 function start$1(name) {
27803   return (name + "").trim().split(/^|\s+/).every(function(t) {
27804     var i = t.indexOf(".");
27805     if (i >= 0) t = t.slice(0, i);
27806     return !t || t === "start";
27807   });
27808 }
27809
27810 function onFunction(id, name, listener) {
27811   var on0, on1, sit = start$1(name) ? init : set$3;
27812   return function() {
27813     var schedule = sit(this, id),
27814         on = schedule.on;
27815
27816     // If this node shared a dispatch with the previous node,
27817     // just assign the updated shared dispatch and we’re done!
27818     // Otherwise, copy-on-write.
27819     if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
27820
27821     schedule.on = on1;
27822   };
27823 }
27824
27825 var transition_on = function(name, listener) {
27826   var id = this._id;
27827
27828   return arguments.length < 2
27829       ? get$1(this.node(), id).on.on(name)
27830       : this.each(onFunction(id, name, listener));
27831 };
27832
27833 function removeFunction(id) {
27834   return function() {
27835     var parent = this.parentNode;
27836     for (var i in this.__transition) if (+i !== id) return;
27837     if (parent) parent.removeChild(this);
27838   };
27839 }
27840
27841 var transition_remove = function() {
27842   return this.on("end.remove", removeFunction(this._id));
27843 };
27844
27845 var transition_select = function(select$$1) {
27846   var name = this._name,
27847       id = this._id;
27848
27849   if (typeof select$$1 !== "function") select$$1 = selector(select$$1);
27850
27851   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
27852     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
27853       if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) {
27854         if ("__data__" in node) subnode.__data__ = node.__data__;
27855         subgroup[i] = subnode;
27856         schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
27857       }
27858     }
27859   }
27860
27861   return new Transition(subgroups, this._parents, name, id);
27862 };
27863
27864 var transition_selectAll = function(select$$1) {
27865   var name = this._name,
27866       id = this._id;
27867
27868   if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1);
27869
27870   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
27871     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
27872       if (node = group[i]) {
27873         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) {
27874           if (child = children[k]) {
27875             schedule(child, name, id, k, children, inherit);
27876           }
27877         }
27878         subgroups.push(children);
27879         parents.push(node);
27880       }
27881     }
27882   }
27883
27884   return new Transition(subgroups, parents, name, id);
27885 };
27886
27887 var Selection$1 = selection.prototype.constructor;
27888
27889 var transition_selection = function() {
27890   return new Selection$1(this._groups, this._parents);
27891 };
27892
27893 function styleRemove$1(name, interpolate$$1) {
27894   var value00,
27895       value10,
27896       interpolate0;
27897   return function() {
27898     var style = window$1(this).getComputedStyle(this, null),
27899         value0 = style.getPropertyValue(name),
27900         value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
27901     return value0 === value1 ? null
27902         : value0 === value00 && value1 === value10 ? interpolate0
27903         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27904   };
27905 }
27906
27907 function styleRemoveEnd(name) {
27908   return function() {
27909     this.style.removeProperty(name);
27910   };
27911 }
27912
27913 function styleConstant$1(name, interpolate$$1, value1) {
27914   var value00,
27915       interpolate0;
27916   return function() {
27917     var value0 = window$1(this).getComputedStyle(this, null).getPropertyValue(name);
27918     return value0 === value1 ? null
27919         : value0 === value00 ? interpolate0
27920         : interpolate0 = interpolate$$1(value00 = value0, value1);
27921   };
27922 }
27923
27924 function styleFunction$1(name, interpolate$$1, value) {
27925   var value00,
27926       value10,
27927       interpolate0;
27928   return function() {
27929     var style = window$1(this).getComputedStyle(this, null),
27930         value0 = style.getPropertyValue(name),
27931         value1 = value(this);
27932     if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
27933     return value0 === value1 ? null
27934         : value0 === value00 && value1 === value10 ? interpolate0
27935         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27936   };
27937 }
27938
27939 var transition_style = function(name, value, priority) {
27940   var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$1;
27941   return value == null ? this
27942           .styleTween(name, styleRemove$1(name, i))
27943           .on("end.style." + name, styleRemoveEnd(name))
27944       : this.styleTween(name, typeof value === "function"
27945           ? styleFunction$1(name, i, tweenValue(this, "style." + name, value))
27946           : styleConstant$1(name, i, value), priority);
27947 };
27948
27949 function styleTween(name, value, priority) {
27950   function tween() {
27951     var node = this, i = value.apply(node, arguments);
27952     return i && function(t) {
27953       node.style.setProperty(name, i(t), priority);
27954     };
27955   }
27956   tween._value = value;
27957   return tween;
27958 }
27959
27960 var transition_styleTween = function(name, value, priority) {
27961   var key = "style." + (name += "");
27962   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
27963   if (value == null) return this.tween(key, null);
27964   if (typeof value !== "function") throw new Error;
27965   return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
27966 };
27967
27968 function textConstant$1(value) {
27969   return function() {
27970     this.textContent = value;
27971   };
27972 }
27973
27974 function textFunction$1(value) {
27975   return function() {
27976     var value1 = value(this);
27977     this.textContent = value1 == null ? "" : value1;
27978   };
27979 }
27980
27981 var transition_text = function(value) {
27982   return this.tween("text", typeof value === "function"
27983       ? textFunction$1(tweenValue(this, "text", value))
27984       : textConstant$1(value == null ? "" : value + ""));
27985 };
27986
27987 var transition_transition = function() {
27988   var name = this._name,
27989       id0 = this._id,
27990       id1 = newId();
27991
27992   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
27993     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
27994       if (node = group[i]) {
27995         var inherit = get$1(node, id0);
27996         schedule(node, name, id1, i, group, {
27997           time: inherit.time + inherit.delay + inherit.duration,
27998           delay: 0,
27999           duration: inherit.duration,
28000           ease: inherit.ease
28001         });
28002       }
28003     }
28004   }
28005
28006   return new Transition(groups, this._parents, name, id1);
28007 };
28008
28009 var id = 0;
28010
28011 function Transition(groups, parents, name, id) {
28012   this._groups = groups;
28013   this._parents = parents;
28014   this._name = name;
28015   this._id = id;
28016 }
28017
28018 function transition(name) {
28019   return selection().transition(name);
28020 }
28021
28022 function newId() {
28023   return ++id;
28024 }
28025
28026 var selection_prototype = selection.prototype;
28027
28028 Transition.prototype = transition.prototype = {
28029   constructor: Transition,
28030   select: transition_select,
28031   selectAll: transition_selectAll,
28032   filter: transition_filter,
28033   merge: transition_merge,
28034   selection: transition_selection,
28035   transition: transition_transition,
28036   call: selection_prototype.call,
28037   nodes: selection_prototype.nodes,
28038   node: selection_prototype.node,
28039   size: selection_prototype.size,
28040   empty: selection_prototype.empty,
28041   each: selection_prototype.each,
28042   on: transition_on,
28043   attr: transition_attr,
28044   attrTween: transition_attrTween,
28045   style: transition_style,
28046   styleTween: transition_styleTween,
28047   text: transition_text,
28048   remove: transition_remove,
28049   tween: transition_tween,
28050   delay: transition_delay,
28051   duration: transition_duration,
28052   ease: transition_ease
28053 };
28054
28055 var defaultTiming = {
28056   time: null, // Set on use.
28057   delay: 0,
28058   duration: 250,
28059   ease: cubicInOut
28060 };
28061
28062 function inherit(node, id) {
28063   var timing;
28064   while (!(timing = node.__transition) || !(timing = timing[id])) {
28065     if (!(node = node.parentNode)) {
28066       return defaultTiming.time = now(), defaultTiming;
28067     }
28068   }
28069   return timing;
28070 }
28071
28072 var selection_transition = function(name) {
28073   var id,
28074       timing;
28075
28076   if (name instanceof Transition) {
28077     id = name._id, name = name._name;
28078   } else {
28079     id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
28080   }
28081
28082   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
28083     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
28084       if (node = group[i]) {
28085         schedule(node, name, id, i, group, timing || inherit(node, id));
28086       }
28087     }
28088   }
28089
28090   return new Transition(groups, this._parents, name, id);
28091 };
28092
28093 selection.prototype.interrupt = selection_interrupt;
28094 selection.prototype.transition = selection_transition;
28095
28096 var root$1 = [null];
28097
28098 var active = function(node, name) {
28099   var schedules = node.__transition,
28100       schedule,
28101       i;
28102
28103   if (schedules) {
28104     name = name == null ? null : name + "";
28105     for (i in schedules) {
28106       if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) {
28107         return new Transition([[node]], root$1, name, +i);
28108       }
28109     }
28110   }
28111
28112   return null;
28113 };
28114
28115 var slice$4 = Array.prototype.slice;
28116
28117 var identity$5 = function(x) {
28118   return x;
28119 };
28120
28121 var top = 1;
28122 var right = 2;
28123 var bottom = 3;
28124 var left = 4;
28125 var epsilon$2 = 1e-6;
28126
28127 function translateX(scale0, scale1, d) {
28128   var x = scale0(d);
28129   return "translate(" + (isFinite(x) ? x : scale1(d)) + ",0)";
28130 }
28131
28132 function translateY(scale0, scale1, d) {
28133   var y = scale0(d);
28134   return "translate(0," + (isFinite(y) ? y : scale1(d)) + ")";
28135 }
28136
28137 function center(scale) {
28138   var offset = scale.bandwidth() / 2;
28139   if (scale.round()) offset = Math.round(offset);
28140   return function(d) {
28141     return scale(d) + offset;
28142   };
28143 }
28144
28145 function entering() {
28146   return !this.__axis;
28147 }
28148
28149 function axis(orient, scale) {
28150   var tickArguments = [],
28151       tickValues = null,
28152       tickFormat = null,
28153       tickSizeInner = 6,
28154       tickSizeOuter = 6,
28155       tickPadding = 3;
28156
28157   function axis(context) {
28158     var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
28159         format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$5) : tickFormat,
28160         spacing = Math.max(tickSizeInner, 0) + tickPadding,
28161         transform = orient === top || orient === bottom ? translateX : translateY,
28162         range = scale.range(),
28163         range0 = range[0] + 0.5,
28164         range1 = range[range.length - 1] + 0.5,
28165         position = (scale.bandwidth ? center : identity$5)(scale.copy()),
28166         selection = context.selection ? context.selection() : context,
28167         path = selection.selectAll(".domain").data([null]),
28168         tick = selection.selectAll(".tick").data(values, scale).order(),
28169         tickExit = tick.exit(),
28170         tickEnter = tick.enter().append("g").attr("class", "tick"),
28171         line = tick.select("line"),
28172         text = tick.select("text"),
28173         k = orient === top || orient === left ? -1 : 1,
28174         x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x");
28175
28176     path = path.merge(path.enter().insert("path", ".tick")
28177         .attr("class", "domain")
28178         .attr("stroke", "#000"));
28179
28180     tick = tick.merge(tickEnter);
28181
28182     line = line.merge(tickEnter.append("line")
28183         .attr("stroke", "#000")
28184         .attr(x + "2", k * tickSizeInner)
28185         .attr(y + "1", 0.5)
28186         .attr(y + "2", 0.5));
28187
28188     text = text.merge(tickEnter.append("text")
28189         .attr("fill", "#000")
28190         .attr(x, k * spacing)
28191         .attr(y, 0.5)
28192         .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
28193
28194     if (context !== selection) {
28195       path = path.transition(context);
28196       tick = tick.transition(context);
28197       line = line.transition(context);
28198       text = text.transition(context);
28199
28200       tickExit = tickExit.transition(context)
28201           .attr("opacity", epsilon$2)
28202           .attr("transform", function(d) { return transform(position, this.parentNode.__axis || position, d); });
28203
28204       tickEnter
28205           .attr("opacity", epsilon$2)
28206           .attr("transform", function(d) { return transform(this.parentNode.__axis || position, position, d); });
28207     }
28208
28209     tickExit.remove();
28210
28211     path
28212         .attr("d", orient === left || orient == right
28213             ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter
28214             : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter);
28215
28216     tick
28217         .attr("opacity", 1)
28218         .attr("transform", function(d) { return transform(position, position, d); });
28219
28220     line
28221         .attr(x + "2", k * tickSizeInner);
28222
28223     text
28224         .attr(x, k * spacing)
28225         .text(format);
28226
28227     selection.filter(entering)
28228         .attr("fill", "none")
28229         .attr("font-size", 10)
28230         .attr("font-family", "sans-serif")
28231         .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
28232
28233     selection
28234         .each(function() { this.__axis = position; });
28235   }
28236
28237   axis.scale = function(_) {
28238     return arguments.length ? (scale = _, axis) : scale;
28239   };
28240
28241   axis.ticks = function() {
28242     return tickArguments = slice$4.call(arguments), axis;
28243   };
28244
28245   axis.tickArguments = function(_) {
28246     return arguments.length ? (tickArguments = _ == null ? [] : slice$4.call(_), axis) : tickArguments.slice();
28247   };
28248
28249   axis.tickValues = function(_) {
28250     return arguments.length ? (tickValues = _ == null ? null : slice$4.call(_), axis) : tickValues && tickValues.slice();
28251   };
28252
28253   axis.tickFormat = function(_) {
28254     return arguments.length ? (tickFormat = _, axis) : tickFormat;
28255   };
28256
28257   axis.tickSize = function(_) {
28258     return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
28259   };
28260
28261   axis.tickSizeInner = function(_) {
28262     return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
28263   };
28264
28265   axis.tickSizeOuter = function(_) {
28266     return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
28267   };
28268
28269   axis.tickPadding = function(_) {
28270     return arguments.length ? (tickPadding = +_, axis) : tickPadding;
28271   };
28272
28273   return axis;
28274 }
28275
28276 function axisTop(scale) {
28277   return axis(top, scale);
28278 }
28279
28280 function axisRight(scale) {
28281   return axis(right, scale);
28282 }
28283
28284 function axisBottom(scale) {
28285   return axis(bottom, scale);
28286 }
28287
28288 function axisLeft(scale) {
28289   return axis(left, scale);
28290 }
28291
28292 function defaultSeparation(a, b) {
28293   return a.parent === b.parent ? 1 : 2;
28294 }
28295
28296 function meanX(children) {
28297   return children.reduce(meanXReduce, 0) / children.length;
28298 }
28299
28300 function meanXReduce(x, c) {
28301   return x + c.x;
28302 }
28303
28304 function maxY(children) {
28305   return 1 + children.reduce(maxYReduce, 0);
28306 }
28307
28308 function maxYReduce(y, c) {
28309   return Math.max(y, c.y);
28310 }
28311
28312 function leafLeft(node) {
28313   var children;
28314   while (children = node.children) node = children[0];
28315   return node;
28316 }
28317
28318 function leafRight(node) {
28319   var children;
28320   while (children = node.children) node = children[children.length - 1];
28321   return node;
28322 }
28323
28324 var cluster = function() {
28325   var separation = defaultSeparation,
28326       dx = 1,
28327       dy = 1,
28328       nodeSize = false;
28329
28330   function cluster(root) {
28331     var previousNode,
28332         x = 0;
28333
28334     // First walk, computing the initial x & y values.
28335     root.eachAfter(function(node) {
28336       var children = node.children;
28337       if (children) {
28338         node.x = meanX(children);
28339         node.y = maxY(children);
28340       } else {
28341         node.x = previousNode ? x += separation(node, previousNode) : 0;
28342         node.y = 0;
28343         previousNode = node;
28344       }
28345     });
28346
28347     var left = leafLeft(root),
28348         right = leafRight(root),
28349         x0 = left.x - separation(left, right) / 2,
28350         x1 = right.x + separation(right, left) / 2;
28351
28352     // Second walk, normalizing x & y to the desired size.
28353     return root.eachAfter(nodeSize ? function(node) {
28354       node.x = (node.x - root.x) * dx;
28355       node.y = (root.y - node.y) * dy;
28356     } : function(node) {
28357       node.x = (node.x - x0) / (x1 - x0) * dx;
28358       node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
28359     });
28360   }
28361
28362   cluster.separation = function(x) {
28363     return arguments.length ? (separation = x, cluster) : separation;
28364   };
28365
28366   cluster.size = function(x) {
28367     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
28368   };
28369
28370   cluster.nodeSize = function(x) {
28371     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
28372   };
28373
28374   return cluster;
28375 };
28376
28377 var node_each = function(callback) {
28378   var node = this, current, next = [node], children, i, n;
28379   do {
28380     current = next.reverse(), next = [];
28381     while (node = current.pop()) {
28382       callback(node), children = node.children;
28383       if (children) for (i = 0, n = children.length; i < n; ++i) {
28384         next.push(children[i]);
28385       }
28386     }
28387   } while (next.length);
28388   return this;
28389 };
28390
28391 var node_eachBefore = function(callback) {
28392   var node = this, nodes = [node], children, i;
28393   while (node = nodes.pop()) {
28394     callback(node), children = node.children;
28395     if (children) for (i = children.length - 1; i >= 0; --i) {
28396       nodes.push(children[i]);
28397     }
28398   }
28399   return this;
28400 };
28401
28402 var node_eachAfter = function(callback) {
28403   var node = this, nodes = [node], next = [], children, i, n;
28404   while (node = nodes.pop()) {
28405     next.push(node), children = node.children;
28406     if (children) for (i = 0, n = children.length; i < n; ++i) {
28407       nodes.push(children[i]);
28408     }
28409   }
28410   while (node = next.pop()) {
28411     callback(node);
28412   }
28413   return this;
28414 };
28415
28416 var node_sum = function(value) {
28417   return this.eachAfter(function(node) {
28418     var sum = +value(node.data) || 0,
28419         children = node.children,
28420         i = children && children.length;
28421     while (--i >= 0) sum += children[i].value;
28422     node.value = sum;
28423   });
28424 };
28425
28426 var node_sort = function(compare) {
28427   return this.eachBefore(function(node) {
28428     if (node.children) {
28429       node.children.sort(compare);
28430     }
28431   });
28432 };
28433
28434 var node_path = function(end) {
28435   var start = this,
28436       ancestor = leastCommonAncestor(start, end),
28437       nodes = [start];
28438   while (start !== ancestor) {
28439     start = start.parent;
28440     nodes.push(start);
28441   }
28442   var k = nodes.length;
28443   while (end !== ancestor) {
28444     nodes.splice(k, 0, end);
28445     end = end.parent;
28446   }
28447   return nodes;
28448 };
28449
28450 function leastCommonAncestor(a, b) {
28451   if (a === b) return a;
28452   var aNodes = a.ancestors(),
28453       bNodes = b.ancestors(),
28454       c = null;
28455   a = aNodes.pop();
28456   b = bNodes.pop();
28457   while (a === b) {
28458     c = a;
28459     a = aNodes.pop();
28460     b = bNodes.pop();
28461   }
28462   return c;
28463 }
28464
28465 var node_ancestors = function() {
28466   var node = this, nodes = [node];
28467   while (node = node.parent) {
28468     nodes.push(node);
28469   }
28470   return nodes;
28471 };
28472
28473 var node_descendants = function() {
28474   var nodes = [];
28475   this.each(function(node) {
28476     nodes.push(node);
28477   });
28478   return nodes;
28479 };
28480
28481 var node_leaves = function() {
28482   var leaves = [];
28483   this.eachBefore(function(node) {
28484     if (!node.children) {
28485       leaves.push(node);
28486     }
28487   });
28488   return leaves;
28489 };
28490
28491 var node_links = function() {
28492   var root = this, links = [];
28493   root.each(function(node) {
28494     if (node !== root) { // Don’t include the root’s parent, if any.
28495       links.push({source: node.parent, target: node});
28496     }
28497   });
28498   return links;
28499 };
28500
28501 function hierarchy(data, children) {
28502   var root = new Node(data),
28503       valued = +data.value && (root.value = data.value),
28504       node,
28505       nodes = [root],
28506       child,
28507       childs,
28508       i,
28509       n;
28510
28511   if (children == null) children = defaultChildren;
28512
28513   while (node = nodes.pop()) {
28514     if (valued) node.value = +node.data.value;
28515     if ((childs = children(node.data)) && (n = childs.length)) {
28516       node.children = new Array(n);
28517       for (i = n - 1; i >= 0; --i) {
28518         nodes.push(child = node.children[i] = new Node(childs[i]));
28519         child.parent = node;
28520         child.depth = node.depth + 1;
28521       }
28522     }
28523   }
28524
28525   return root.eachBefore(computeHeight);
28526 }
28527
28528 function node_copy() {
28529   return hierarchy(this).eachBefore(copyData);
28530 }
28531
28532 function defaultChildren(d) {
28533   return d.children;
28534 }
28535
28536 function copyData(node) {
28537   node.data = node.data.data;
28538 }
28539
28540 function computeHeight(node) {
28541   var height = 0;
28542   do node.height = height;
28543   while ((node = node.parent) && (node.height < ++height));
28544 }
28545
28546 function Node(data) {
28547   this.data = data;
28548   this.depth =
28549   this.height = 0;
28550   this.parent = null;
28551 }
28552
28553 Node.prototype = hierarchy.prototype = {
28554   constructor: Node,
28555   each: node_each,
28556   eachAfter: node_eachAfter,
28557   eachBefore: node_eachBefore,
28558   sum: node_sum,
28559   sort: node_sort,
28560   path: node_path,
28561   ancestors: node_ancestors,
28562   descendants: node_descendants,
28563   leaves: node_leaves,
28564   links: node_links,
28565   copy: node_copy
28566 };
28567
28568 function Node$2(value) {
28569   this._ = value;
28570   this.next = null;
28571 }
28572
28573 var shuffle$1 = function(array) {
28574   var i,
28575       n = (array = array.slice()).length,
28576       head = null,
28577       node = head;
28578
28579   while (n) {
28580     var next = new Node$2(array[n - 1]);
28581     if (node) node = node.next = next;
28582     else node = head = next;
28583     array[i] = array[--n];
28584   }
28585
28586   return {
28587     head: head,
28588     tail: node
28589   };
28590 };
28591
28592 var enclose = function(circles) {
28593   return encloseN(shuffle$1(circles), []);
28594 };
28595
28596 function encloses(a, b) {
28597   var dx = b.x - a.x,
28598       dy = b.y - a.y,
28599       dr = a.r - b.r;
28600   return dr * dr + 1e-6 > dx * dx + dy * dy;
28601 }
28602
28603 // Returns the smallest circle that contains circles L and intersects circles B.
28604 function encloseN(L, B) {
28605   var circle,
28606       l0 = null,
28607       l1 = L.head,
28608       l2,
28609       p1;
28610
28611   switch (B.length) {
28612     case 1: circle = enclose1(B[0]); break;
28613     case 2: circle = enclose2(B[0], B[1]); break;
28614     case 3: circle = enclose3(B[0], B[1], B[2]); break;
28615   }
28616
28617   while (l1) {
28618     p1 = l1._, l2 = l1.next;
28619     if (!circle || !encloses(circle, p1)) {
28620
28621       // Temporarily truncate L before l1.
28622       if (l0) L.tail = l0, l0.next = null;
28623       else L.head = L.tail = null;
28624
28625       B.push(p1);
28626       circle = encloseN(L, B); // Note: reorders L!
28627       B.pop();
28628
28629       // Move l1 to the front of L and reconnect the truncated list L.
28630       if (L.head) l1.next = L.head, L.head = l1;
28631       else l1.next = null, L.head = L.tail = l1;
28632       l0 = L.tail, l0.next = l2;
28633
28634     } else {
28635       l0 = l1;
28636     }
28637     l1 = l2;
28638   }
28639
28640   L.tail = l0;
28641   return circle;
28642 }
28643
28644 function enclose1(a) {
28645   return {
28646     x: a.x,
28647     y: a.y,
28648     r: a.r
28649   };
28650 }
28651
28652 function enclose2(a, b) {
28653   var x1 = a.x, y1 = a.y, r1 = a.r,
28654       x2 = b.x, y2 = b.y, r2 = b.r,
28655       x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
28656       l = Math.sqrt(x21 * x21 + y21 * y21);
28657   return {
28658     x: (x1 + x2 + x21 / l * r21) / 2,
28659     y: (y1 + y2 + y21 / l * r21) / 2,
28660     r: (l + r1 + r2) / 2
28661   };
28662 }
28663
28664 function enclose3(a, b, c) {
28665   var x1 = a.x, y1 = a.y, r1 = a.r,
28666       x2 = b.x, y2 = b.y, r2 = b.r,
28667       x3 = c.x, y3 = c.y, r3 = c.r,
28668       a2 = 2 * (x1 - x2),
28669       b2 = 2 * (y1 - y2),
28670       c2 = 2 * (r2 - r1),
28671       d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
28672       a3 = 2 * (x1 - x3),
28673       b3 = 2 * (y1 - y3),
28674       c3 = 2 * (r3 - r1),
28675       d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
28676       ab = a3 * b2 - a2 * b3,
28677       xa = (b2 * d3 - b3 * d2) / ab - x1,
28678       xb = (b3 * c2 - b2 * c3) / ab,
28679       ya = (a3 * d2 - a2 * d3) / ab - y1,
28680       yb = (a2 * c3 - a3 * c2) / ab,
28681       A = xb * xb + yb * yb - 1,
28682       B = 2 * (xa * xb + ya * yb + r1),
28683       C = xa * xa + ya * ya - r1 * r1,
28684       r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
28685   return {
28686     x: xa + xb * r + x1,
28687     y: ya + yb * r + y1,
28688     r: r
28689   };
28690 }
28691
28692 function place(a, b, c) {
28693   var ax = a.x,
28694       ay = a.y,
28695       da = b.r + c.r,
28696       db = a.r + c.r,
28697       dx = b.x - ax,
28698       dy = b.y - ay,
28699       dc = dx * dx + dy * dy;
28700   if (dc) {
28701     var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
28702         y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
28703     c.x = ax + x * dx + y * dy;
28704     c.y = ay + x * dy - y * dx;
28705   } else {
28706     c.x = ax + db;
28707     c.y = ay;
28708   }
28709 }
28710
28711 function intersects(a, b) {
28712   var dx = b.x - a.x,
28713       dy = b.y - a.y,
28714       dr = a.r + b.r;
28715   return dr * dr > dx * dx + dy * dy;
28716 }
28717
28718 function distance2(circle, x, y) {
28719   var dx = circle.x - x,
28720       dy = circle.y - y;
28721   return dx * dx + dy * dy;
28722 }
28723
28724 function Node$1(circle) {
28725   this._ = circle;
28726   this.next = null;
28727   this.previous = null;
28728 }
28729
28730 function packEnclose(circles) {
28731   if (!(n = circles.length)) return 0;
28732
28733   var a, b, c, n;
28734
28735   // Place the first circle.
28736   a = circles[0], a.x = 0, a.y = 0;
28737   if (!(n > 1)) return a.r;
28738
28739   // Place the second circle.
28740   b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
28741   if (!(n > 2)) return a.r + b.r;
28742
28743   // Place the third circle.
28744   place(b, a, c = circles[2]);
28745
28746   // Initialize the weighted centroid.
28747   var aa = a.r * a.r,
28748       ba = b.r * b.r,
28749       ca = c.r * c.r,
28750       oa = aa + ba + ca,
28751       ox = aa * a.x + ba * b.x + ca * c.x,
28752       oy = aa * a.y + ba * b.y + ca * c.y,
28753       cx, cy, i, j, k, sj, sk;
28754
28755   // Initialize the front-chain using the first three circles a, b and c.
28756   a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
28757   a.next = c.previous = b;
28758   b.next = a.previous = c;
28759   c.next = b.previous = a;
28760
28761   // Attempt to place each remaining circle…
28762   pack: for (i = 3; i < n; ++i) {
28763     place(a._, b._, c = circles[i]), c = new Node$1(c);
28764
28765     // If there are only three elements in the front-chain…
28766     if ((k = a.previous) === (j = b.next)) {
28767       // If the new circle intersects the third circle,
28768       // rotate the front chain to try the next position.
28769       if (intersects(j._, c._)) {
28770         a = b, b = j, --i;
28771         continue pack;
28772       }
28773     }
28774
28775     // Find the closest intersecting circle on the front-chain, if any.
28776     else {
28777       sj = j._.r, sk = k._.r;
28778       do {
28779         if (sj <= sk) {
28780           if (intersects(j._, c._)) {
28781             b = j, a.next = b, b.previous = a, --i;
28782             continue pack;
28783           }
28784           j = j.next, sj += j._.r;
28785         } else {
28786           if (intersects(k._, c._)) {
28787             a = k, a.next = b, b.previous = a, --i;
28788             continue pack;
28789           }
28790           k = k.previous, sk += k._.r;
28791         }
28792       } while (j !== k.next);
28793     }
28794
28795     // Success! Insert the new circle c between a and b.
28796     c.previous = a, c.next = b, a.next = b.previous = b = c;
28797
28798     // Update the weighted centroid.
28799     oa += ca = c._.r * c._.r;
28800     ox += ca * c._.x;
28801     oy += ca * c._.y;
28802
28803     // Compute the new closest circle a to centroid.
28804     aa = distance2(a._, cx = ox / oa, cy = oy / oa);
28805     while ((c = c.next) !== b) {
28806       if ((ca = distance2(c._, cx, cy)) < aa) {
28807         a = c, aa = ca;
28808       }
28809     }
28810     b = a.next;
28811   }
28812
28813   // Compute the enclosing circle of the front chain.
28814   a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
28815
28816   // Translate the circles to put the enclosing circle around the origin.
28817   for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
28818
28819   return c.r;
28820 }
28821
28822 var siblings = function(circles) {
28823   packEnclose(circles);
28824   return circles;
28825 };
28826
28827 function optional(f) {
28828   return f == null ? null : required(f);
28829 }
28830
28831 function required(f) {
28832   if (typeof f !== "function") throw new Error;
28833   return f;
28834 }
28835
28836 function constantZero() {
28837   return 0;
28838 }
28839
28840 var constant$6 = function(x) {
28841   return function() {
28842     return x;
28843   };
28844 };
28845
28846 function defaultRadius(d) {
28847   return Math.sqrt(d.value);
28848 }
28849
28850 var index$2 = function() {
28851   var radius = null,
28852       dx = 1,
28853       dy = 1,
28854       padding = constantZero;
28855
28856   function pack(root) {
28857     root.x = dx / 2, root.y = dy / 2;
28858     if (radius) {
28859       root.eachBefore(radiusLeaf(radius))
28860           .eachAfter(packChildren(padding, 0.5))
28861           .eachBefore(translateChild(1));
28862     } else {
28863       root.eachBefore(radiusLeaf(defaultRadius))
28864           .eachAfter(packChildren(constantZero, 1))
28865           .eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
28866           .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
28867     }
28868     return root;
28869   }
28870
28871   pack.radius = function(x) {
28872     return arguments.length ? (radius = optional(x), pack) : radius;
28873   };
28874
28875   pack.size = function(x) {
28876     return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
28877   };
28878
28879   pack.padding = function(x) {
28880     return arguments.length ? (padding = typeof x === "function" ? x : constant$6(+x), pack) : padding;
28881   };
28882
28883   return pack;
28884 };
28885
28886 function radiusLeaf(radius) {
28887   return function(node) {
28888     if (!node.children) {
28889       node.r = Math.max(0, +radius(node) || 0);
28890     }
28891   };
28892 }
28893
28894 function packChildren(padding, k) {
28895   return function(node) {
28896     if (children = node.children) {
28897       var children,
28898           i,
28899           n = children.length,
28900           r = padding(node) * k || 0,
28901           e;
28902
28903       if (r) for (i = 0; i < n; ++i) children[i].r += r;
28904       e = packEnclose(children);
28905       if (r) for (i = 0; i < n; ++i) children[i].r -= r;
28906       node.r = e + r;
28907     }
28908   };
28909 }
28910
28911 function translateChild(k) {
28912   return function(node) {
28913     var parent = node.parent;
28914     node.r *= k;
28915     if (parent) {
28916       node.x = parent.x + k * node.x;
28917       node.y = parent.y + k * node.y;
28918     }
28919   };
28920 }
28921
28922 var roundNode = function(node) {
28923   node.x0 = Math.round(node.x0);
28924   node.y0 = Math.round(node.y0);
28925   node.x1 = Math.round(node.x1);
28926   node.y1 = Math.round(node.y1);
28927 };
28928
28929 var treemapDice = function(parent, x0, y0, x1, y1) {
28930   var nodes = parent.children,
28931       node,
28932       i = -1,
28933       n = nodes.length,
28934       k = parent.value && (x1 - x0) / parent.value;
28935
28936   while (++i < n) {
28937     node = nodes[i], node.y0 = y0, node.y1 = y1;
28938     node.x0 = x0, node.x1 = x0 += node.value * k;
28939   }
28940 };
28941
28942 var partition = function() {
28943   var dx = 1,
28944       dy = 1,
28945       padding = 0,
28946       round = false;
28947
28948   function partition(root) {
28949     var n = root.height + 1;
28950     root.x0 =
28951     root.y0 = padding;
28952     root.x1 = dx;
28953     root.y1 = dy / n;
28954     root.eachBefore(positionNode(dy, n));
28955     if (round) root.eachBefore(roundNode);
28956     return root;
28957   }
28958
28959   function positionNode(dy, n) {
28960     return function(node) {
28961       if (node.children) {
28962         treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
28963       }
28964       var x0 = node.x0,
28965           y0 = node.y0,
28966           x1 = node.x1 - padding,
28967           y1 = node.y1 - padding;
28968       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
28969       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
28970       node.x0 = x0;
28971       node.y0 = y0;
28972       node.x1 = x1;
28973       node.y1 = y1;
28974     };
28975   }
28976
28977   partition.round = function(x) {
28978     return arguments.length ? (round = !!x, partition) : round;
28979   };
28980
28981   partition.size = function(x) {
28982     return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
28983   };
28984
28985   partition.padding = function(x) {
28986     return arguments.length ? (padding = +x, partition) : padding;
28987   };
28988
28989   return partition;
28990 };
28991
28992 var keyPrefix$1 = "$";
28993 var preroot = {depth: -1};
28994 var ambiguous = {};
28995
28996 function defaultId(d) {
28997   return d.id;
28998 }
28999
29000 function defaultParentId(d) {
29001   return d.parentId;
29002 }
29003
29004 var stratify = function() {
29005   var id = defaultId,
29006       parentId = defaultParentId;
29007
29008   function stratify(data) {
29009     var d,
29010         i,
29011         n = data.length,
29012         root,
29013         parent,
29014         node,
29015         nodes = new Array(n),
29016         nodeId,
29017         nodeKey,
29018         nodeByKey = {};
29019
29020     for (i = 0; i < n; ++i) {
29021       d = data[i], node = nodes[i] = new Node(d);
29022       if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
29023         nodeKey = keyPrefix$1 + (node.id = nodeId);
29024         nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
29025       }
29026     }
29027
29028     for (i = 0; i < n; ++i) {
29029       node = nodes[i], nodeId = parentId(data[i], i, data);
29030       if (nodeId == null || !(nodeId += "")) {
29031         if (root) throw new Error("multiple roots");
29032         root = node;
29033       } else {
29034         parent = nodeByKey[keyPrefix$1 + nodeId];
29035         if (!parent) throw new Error("missing: " + nodeId);
29036         if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
29037         if (parent.children) parent.children.push(node);
29038         else parent.children = [node];
29039         node.parent = parent;
29040       }
29041     }
29042
29043     if (!root) throw new Error("no root");
29044     root.parent = preroot;
29045     root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
29046     root.parent = null;
29047     if (n > 0) throw new Error("cycle");
29048
29049     return root;
29050   }
29051
29052   stratify.id = function(x) {
29053     return arguments.length ? (id = required(x), stratify) : id;
29054   };
29055
29056   stratify.parentId = function(x) {
29057     return arguments.length ? (parentId = required(x), stratify) : parentId;
29058   };
29059
29060   return stratify;
29061 };
29062
29063 function defaultSeparation$1(a, b) {
29064   return a.parent === b.parent ? 1 : 2;
29065 }
29066
29067 // function radialSeparation(a, b) {
29068 //   return (a.parent === b.parent ? 1 : 2) / a.depth;
29069 // }
29070
29071 // This function is used to traverse the left contour of a subtree (or
29072 // subforest). It returns the successor of v on this contour. This successor is
29073 // either given by the leftmost child of v or by the thread of v. The function
29074 // returns null if and only if v is on the highest level of its subtree.
29075 function nextLeft(v) {
29076   var children = v.children;
29077   return children ? children[0] : v.t;
29078 }
29079
29080 // This function works analogously to nextLeft.
29081 function nextRight(v) {
29082   var children = v.children;
29083   return children ? children[children.length - 1] : v.t;
29084 }
29085
29086 // Shifts the current subtree rooted at w+. This is done by increasing
29087 // prelim(w+) and mod(w+) by shift.
29088 function moveSubtree(wm, wp, shift) {
29089   var change = shift / (wp.i - wm.i);
29090   wp.c -= change;
29091   wp.s += shift;
29092   wm.c += change;
29093   wp.z += shift;
29094   wp.m += shift;
29095 }
29096
29097 // All other shifts, applied to the smaller subtrees between w- and w+, are
29098 // performed by this function. To prepare the shifts, we have to adjust
29099 // change(w+), shift(w+), and change(w-).
29100 function executeShifts(v) {
29101   var shift = 0,
29102       change = 0,
29103       children = v.children,
29104       i = children.length,
29105       w;
29106   while (--i >= 0) {
29107     w = children[i];
29108     w.z += shift;
29109     w.m += shift;
29110     shift += w.s + (change += w.c);
29111   }
29112 }
29113
29114 // If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
29115 // returns the specified (default) ancestor.
29116 function nextAncestor(vim, v, ancestor) {
29117   return vim.a.parent === v.parent ? vim.a : ancestor;
29118 }
29119
29120 function TreeNode(node, i) {
29121   this._ = node;
29122   this.parent = null;
29123   this.children = null;
29124   this.A = null; // default ancestor
29125   this.a = this; // ancestor
29126   this.z = 0; // prelim
29127   this.m = 0; // mod
29128   this.c = 0; // change
29129   this.s = 0; // shift
29130   this.t = null; // thread
29131   this.i = i; // number
29132 }
29133
29134 TreeNode.prototype = Object.create(Node.prototype);
29135
29136 function treeRoot(root) {
29137   var tree = new TreeNode(root, 0),
29138       node,
29139       nodes = [tree],
29140       child,
29141       children,
29142       i,
29143       n;
29144
29145   while (node = nodes.pop()) {
29146     if (children = node._.children) {
29147       node.children = new Array(n = children.length);
29148       for (i = n - 1; i >= 0; --i) {
29149         nodes.push(child = node.children[i] = new TreeNode(children[i], i));
29150         child.parent = node;
29151       }
29152     }
29153   }
29154
29155   (tree.parent = new TreeNode(null, 0)).children = [tree];
29156   return tree;
29157 }
29158
29159 // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
29160 var tree = function() {
29161   var separation = defaultSeparation$1,
29162       dx = 1,
29163       dy = 1,
29164       nodeSize = null;
29165
29166   function tree(root) {
29167     var t = treeRoot(root);
29168
29169     // Compute the layout using Buchheim et al.’s algorithm.
29170     t.eachAfter(firstWalk), t.parent.m = -t.z;
29171     t.eachBefore(secondWalk);
29172
29173     // If a fixed node size is specified, scale x and y.
29174     if (nodeSize) root.eachBefore(sizeNode);
29175
29176     // If a fixed tree size is specified, scale x and y based on the extent.
29177     // Compute the left-most, right-most, and depth-most nodes for extents.
29178     else {
29179       var left = root,
29180           right = root,
29181           bottom = root;
29182       root.eachBefore(function(node) {
29183         if (node.x < left.x) left = node;
29184         if (node.x > right.x) right = node;
29185         if (node.depth > bottom.depth) bottom = node;
29186       });
29187       var s = left === right ? 1 : separation(left, right) / 2,
29188           tx = s - left.x,
29189           kx = dx / (right.x + s + tx),
29190           ky = dy / (bottom.depth || 1);
29191       root.eachBefore(function(node) {
29192         node.x = (node.x + tx) * kx;
29193         node.y = node.depth * ky;
29194       });
29195     }
29196
29197     return root;
29198   }
29199
29200   // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
29201   // applied recursively to the children of v, as well as the function
29202   // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
29203   // node v is placed to the midpoint of its outermost children.
29204   function firstWalk(v) {
29205     var children = v.children,
29206         siblings = v.parent.children,
29207         w = v.i ? siblings[v.i - 1] : null;
29208     if (children) {
29209       executeShifts(v);
29210       var midpoint = (children[0].z + children[children.length - 1].z) / 2;
29211       if (w) {
29212         v.z = w.z + separation(v._, w._);
29213         v.m = v.z - midpoint;
29214       } else {
29215         v.z = midpoint;
29216       }
29217     } else if (w) {
29218       v.z = w.z + separation(v._, w._);
29219     }
29220     v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
29221   }
29222
29223   // Computes all real x-coordinates by summing up the modifiers recursively.
29224   function secondWalk(v) {
29225     v._.x = v.z + v.parent.m;
29226     v.m += v.parent.m;
29227   }
29228
29229   // The core of the algorithm. Here, a new subtree is combined with the
29230   // previous subtrees. Threads are used to traverse the inside and outside
29231   // contours of the left and right subtree up to the highest common level. The
29232   // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
29233   // superscript o means outside and i means inside, the subscript - means left
29234   // subtree and + means right subtree. For summing up the modifiers along the
29235   // contour, we use respective variables si+, si-, so-, and so+. Whenever two
29236   // nodes of the inside contours conflict, we compute the left one of the
29237   // greatest uncommon ancestors using the function ANCESTOR and call MOVE
29238   // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
29239   // Finally, we add a new thread (if necessary).
29240   function apportion(v, w, ancestor) {
29241     if (w) {
29242       var vip = v,
29243           vop = v,
29244           vim = w,
29245           vom = vip.parent.children[0],
29246           sip = vip.m,
29247           sop = vop.m,
29248           sim = vim.m,
29249           som = vom.m,
29250           shift;
29251       while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
29252         vom = nextLeft(vom);
29253         vop = nextRight(vop);
29254         vop.a = v;
29255         shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
29256         if (shift > 0) {
29257           moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
29258           sip += shift;
29259           sop += shift;
29260         }
29261         sim += vim.m;
29262         sip += vip.m;
29263         som += vom.m;
29264         sop += vop.m;
29265       }
29266       if (vim && !nextRight(vop)) {
29267         vop.t = vim;
29268         vop.m += sim - sop;
29269       }
29270       if (vip && !nextLeft(vom)) {
29271         vom.t = vip;
29272         vom.m += sip - som;
29273         ancestor = v;
29274       }
29275     }
29276     return ancestor;
29277   }
29278
29279   function sizeNode(node) {
29280     node.x *= dx;
29281     node.y = node.depth * dy;
29282   }
29283
29284   tree.separation = function(x) {
29285     return arguments.length ? (separation = x, tree) : separation;
29286   };
29287
29288   tree.size = function(x) {
29289     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
29290   };
29291
29292   tree.nodeSize = function(x) {
29293     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
29294   };
29295
29296   return tree;
29297 };
29298
29299 var treemapSlice = function(parent, x0, y0, x1, y1) {
29300   var nodes = parent.children,
29301       node,
29302       i = -1,
29303       n = nodes.length,
29304       k = parent.value && (y1 - y0) / parent.value;
29305
29306   while (++i < n) {
29307     node = nodes[i], node.x0 = x0, node.x1 = x1;
29308     node.y0 = y0, node.y1 = y0 += node.value * k;
29309   }
29310 };
29311
29312 var phi = (1 + Math.sqrt(5)) / 2;
29313
29314 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
29315   var rows = [],
29316       nodes = parent.children,
29317       row,
29318       nodeValue,
29319       i0 = 0,
29320       i1,
29321       n = nodes.length,
29322       dx, dy,
29323       value = parent.value,
29324       sumValue,
29325       minValue,
29326       maxValue,
29327       newRatio,
29328       minRatio,
29329       alpha,
29330       beta;
29331
29332   while (i0 < n) {
29333     dx = x1 - x0, dy = y1 - y0;
29334     minValue = maxValue = sumValue = nodes[i0].value;
29335     alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
29336     beta = sumValue * sumValue * alpha;
29337     minRatio = Math.max(maxValue / beta, beta / minValue);
29338
29339     // Keep adding nodes while the aspect ratio maintains or improves.
29340     for (i1 = i0 + 1; i1 < n; ++i1) {
29341       sumValue += nodeValue = nodes[i1].value;
29342       if (nodeValue < minValue) minValue = nodeValue;
29343       if (nodeValue > maxValue) maxValue = nodeValue;
29344       beta = sumValue * sumValue * alpha;
29345       newRatio = Math.max(maxValue / beta, beta / minValue);
29346       if (newRatio > minRatio) { sumValue -= nodeValue; break; }
29347       minRatio = newRatio;
29348     }
29349
29350     // Position and record the row orientation.
29351     rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
29352     if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
29353     else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
29354     value -= sumValue, i0 = i1;
29355   }
29356
29357   return rows;
29358 }
29359
29360 var squarify = (function custom(ratio) {
29361
29362   function squarify(parent, x0, y0, x1, y1) {
29363     squarifyRatio(ratio, parent, x0, y0, x1, y1);
29364   }
29365
29366   squarify.ratio = function(x) {
29367     return custom((x = +x) > 1 ? x : 1);
29368   };
29369
29370   return squarify;
29371 })(phi);
29372
29373 var index$3 = function() {
29374   var tile = squarify,
29375       round = false,
29376       dx = 1,
29377       dy = 1,
29378       paddingStack = [0],
29379       paddingInner = constantZero,
29380       paddingTop = constantZero,
29381       paddingRight = constantZero,
29382       paddingBottom = constantZero,
29383       paddingLeft = constantZero;
29384
29385   function treemap(root) {
29386     root.x0 =
29387     root.y0 = 0;
29388     root.x1 = dx;
29389     root.y1 = dy;
29390     root.eachBefore(positionNode);
29391     paddingStack = [0];
29392     if (round) root.eachBefore(roundNode);
29393     return root;
29394   }
29395
29396   function positionNode(node) {
29397     var p = paddingStack[node.depth],
29398         x0 = node.x0 + p,
29399         y0 = node.y0 + p,
29400         x1 = node.x1 - p,
29401         y1 = node.y1 - p;
29402     if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29403     if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29404     node.x0 = x0;
29405     node.y0 = y0;
29406     node.x1 = x1;
29407     node.y1 = y1;
29408     if (node.children) {
29409       p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
29410       x0 += paddingLeft(node) - p;
29411       y0 += paddingTop(node) - p;
29412       x1 -= paddingRight(node) - p;
29413       y1 -= paddingBottom(node) - p;
29414       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29415       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29416       tile(node, x0, y0, x1, y1);
29417     }
29418   }
29419
29420   treemap.round = function(x) {
29421     return arguments.length ? (round = !!x, treemap) : round;
29422   };
29423
29424   treemap.size = function(x) {
29425     return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
29426   };
29427
29428   treemap.tile = function(x) {
29429     return arguments.length ? (tile = required(x), treemap) : tile;
29430   };
29431
29432   treemap.padding = function(x) {
29433     return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
29434   };
29435
29436   treemap.paddingInner = function(x) {
29437     return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$6(+x), treemap) : paddingInner;
29438   };
29439
29440   treemap.paddingOuter = function(x) {
29441     return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
29442   };
29443
29444   treemap.paddingTop = function(x) {
29445     return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$6(+x), treemap) : paddingTop;
29446   };
29447
29448   treemap.paddingRight = function(x) {
29449     return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$6(+x), treemap) : paddingRight;
29450   };
29451
29452   treemap.paddingBottom = function(x) {
29453     return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$6(+x), treemap) : paddingBottom;
29454   };
29455
29456   treemap.paddingLeft = function(x) {
29457     return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$6(+x), treemap) : paddingLeft;
29458   };
29459
29460   return treemap;
29461 };
29462
29463 var binary = function(parent, x0, y0, x1, y1) {
29464   var nodes = parent.children,
29465       i, n = nodes.length,
29466       sum, sums = new Array(n + 1);
29467
29468   for (sums[0] = sum = i = 0; i < n; ++i) {
29469     sums[i + 1] = sum += nodes[i].value;
29470   }
29471
29472   partition(0, n, parent.value, x0, y0, x1, y1);
29473
29474   function partition(i, j, value, x0, y0, x1, y1) {
29475     if (i >= j - 1) {
29476       var node = nodes[i];
29477       node.x0 = x0, node.y0 = y0;
29478       node.x1 = x1, node.y1 = y1;
29479       return;
29480     }
29481
29482     var valueOffset = sums[i],
29483         valueTarget = (value / 2) + valueOffset,
29484         k = i + 1,
29485         hi = j - 1;
29486
29487     while (k < hi) {
29488       var mid = k + hi >>> 1;
29489       if (sums[mid] < valueTarget) k = mid + 1;
29490       else hi = mid;
29491     }
29492
29493     var valueLeft = sums[k] - valueOffset,
29494         valueRight = value - valueLeft;
29495
29496     if ((y1 - y0) > (x1 - x0)) {
29497       var yk = (y0 * valueRight + y1 * valueLeft) / value;
29498       partition(i, k, valueLeft, x0, y0, x1, yk);
29499       partition(k, j, valueRight, x0, yk, x1, y1);
29500     } else {
29501       var xk = (x0 * valueRight + x1 * valueLeft) / value;
29502       partition(i, k, valueLeft, x0, y0, xk, y1);
29503       partition(k, j, valueRight, xk, y0, x1, y1);
29504     }
29505   }
29506 };
29507
29508 var sliceDice = function(parent, x0, y0, x1, y1) {
29509   (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
29510 };
29511
29512 var resquarify = (function custom(ratio) {
29513
29514   function resquarify(parent, x0, y0, x1, y1) {
29515     if ((rows = parent._squarify) && (rows.ratio === ratio)) {
29516       var rows,
29517           row,
29518           nodes,
29519           i,
29520           j = -1,
29521           n,
29522           m = rows.length,
29523           value = parent.value;
29524
29525       while (++j < m) {
29526         row = rows[j], nodes = row.children;
29527         for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
29528         if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
29529         else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
29530         value -= row.value;
29531       }
29532     } else {
29533       parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
29534       rows.ratio = ratio;
29535     }
29536   }
29537
29538   resquarify.ratio = function(x) {
29539     return custom((x = +x) > 1 ? x : 1);
29540   };
29541
29542   return resquarify;
29543 })(phi);
29544
29545 var center$1 = function(x, y) {
29546   var nodes;
29547
29548   if (x == null) x = 0;
29549   if (y == null) y = 0;
29550
29551   function force() {
29552     var i,
29553         n = nodes.length,
29554         node,
29555         sx = 0,
29556         sy = 0;
29557
29558     for (i = 0; i < n; ++i) {
29559       node = nodes[i], sx += node.x, sy += node.y;
29560     }
29561
29562     for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
29563       node = nodes[i], node.x -= sx, node.y -= sy;
29564     }
29565   }
29566
29567   force.initialize = function(_) {
29568     nodes = _;
29569   };
29570
29571   force.x = function(_) {
29572     return arguments.length ? (x = +_, force) : x;
29573   };
29574
29575   force.y = function(_) {
29576     return arguments.length ? (y = +_, force) : y;
29577   };
29578
29579   return force;
29580 };
29581
29582 var constant$7 = function(x) {
29583   return function() {
29584     return x;
29585   };
29586 };
29587
29588 var jiggle = function() {
29589   return (Math.random() - 0.5) * 1e-6;
29590 };
29591
29592 function x$1(d) {
29593   return d.x + d.vx;
29594 }
29595
29596 function y$1(d) {
29597   return d.y + d.vy;
29598 }
29599
29600 var collide = function(radius) {
29601   var nodes,
29602       radii,
29603       strength = 1,
29604       iterations = 1;
29605
29606   if (typeof radius !== "function") radius = constant$7(radius == null ? 1 : +radius);
29607
29608   function force() {
29609     var i, n = nodes.length,
29610         tree,
29611         node,
29612         xi,
29613         yi,
29614         ri,
29615         ri2;
29616
29617     for (var k = 0; k < iterations; ++k) {
29618       tree = quadtree(nodes, x$1, y$1).visitAfter(prepare);
29619       for (i = 0; i < n; ++i) {
29620         node = nodes[i];
29621         ri = radii[i], ri2 = ri * ri;
29622         xi = node.x + node.vx;
29623         yi = node.y + node.vy;
29624         tree.visit(apply);
29625       }
29626     }
29627
29628     function apply(quad, x0, y0, x1, y1) {
29629       var data = quad.data, rj = quad.r, r = ri + rj;
29630       if (data) {
29631         if (data.index > i) {
29632           var x = xi - data.x - data.vx,
29633               y = yi - data.y - data.vy,
29634               l = x * x + y * y;
29635           if (l < r * r) {
29636             if (x === 0) x = jiggle(), l += x * x;
29637             if (y === 0) y = jiggle(), l += y * y;
29638             l = (r - (l = Math.sqrt(l))) / l * strength;
29639             node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
29640             node.vy += (y *= l) * r;
29641             data.vx -= x * (r = 1 - r);
29642             data.vy -= y * r;
29643           }
29644         }
29645         return;
29646       }
29647       return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
29648     }
29649   }
29650
29651   function prepare(quad) {
29652     if (quad.data) return quad.r = radii[quad.data.index];
29653     for (var i = quad.r = 0; i < 4; ++i) {
29654       if (quad[i] && quad[i].r > quad.r) {
29655         quad.r = quad[i].r;
29656       }
29657     }
29658   }
29659
29660   function initialize() {
29661     if (!nodes) return;
29662     var i, n = nodes.length;
29663     radii = new Array(n);
29664     for (i = 0; i < n; ++i) radii[i] = +radius(nodes[i], i, nodes);
29665   }
29666
29667   force.initialize = function(_) {
29668     nodes = _;
29669     initialize();
29670   };
29671
29672   force.iterations = function(_) {
29673     return arguments.length ? (iterations = +_, force) : iterations;
29674   };
29675
29676   force.strength = function(_) {
29677     return arguments.length ? (strength = +_, force) : strength;
29678   };
29679
29680   force.radius = function(_) {
29681     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : radius;
29682   };
29683
29684   return force;
29685 };
29686
29687 function index$4(d, i) {
29688   return i;
29689 }
29690
29691 function find(nodeById, nodeId) {
29692   var node = nodeById.get(nodeId);
29693   if (!node) throw new Error("missing: " + nodeId);
29694   return node;
29695 }
29696
29697 var link = function(links) {
29698   var id = index$4,
29699       strength = defaultStrength,
29700       strengths,
29701       distance = constant$7(30),
29702       distances,
29703       nodes,
29704       count,
29705       bias,
29706       iterations = 1;
29707
29708   if (links == null) links = [];
29709
29710   function defaultStrength(link) {
29711     return 1 / Math.min(count[link.source.index], count[link.target.index]);
29712   }
29713
29714   function force(alpha) {
29715     for (var k = 0, n = links.length; k < iterations; ++k) {
29716       for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
29717         link = links[i], source = link.source, target = link.target;
29718         x = target.x + target.vx - source.x - source.vx || jiggle();
29719         y = target.y + target.vy - source.y - source.vy || jiggle();
29720         l = Math.sqrt(x * x + y * y);
29721         l = (l - distances[i]) / l * alpha * strengths[i];
29722         x *= l, y *= l;
29723         target.vx -= x * (b = bias[i]);
29724         target.vy -= y * b;
29725         source.vx += x * (b = 1 - b);
29726         source.vy += y * b;
29727       }
29728     }
29729   }
29730
29731   function initialize() {
29732     if (!nodes) return;
29733
29734     var i,
29735         n = nodes.length,
29736         m = links.length,
29737         nodeById = map$1(nodes, id),
29738         link;
29739
29740     for (i = 0, count = new Array(n); i < n; ++i) {
29741       count[i] = 0;
29742     }
29743
29744     for (i = 0; i < m; ++i) {
29745       link = links[i], link.index = i;
29746       if (typeof link.source !== "object") link.source = find(nodeById, link.source);
29747       if (typeof link.target !== "object") link.target = find(nodeById, link.target);
29748       ++count[link.source.index], ++count[link.target.index];
29749     }
29750
29751     for (i = 0, bias = new Array(m); i < m; ++i) {
29752       link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
29753     }
29754
29755     strengths = new Array(m), initializeStrength();
29756     distances = new Array(m), initializeDistance();
29757   }
29758
29759   function initializeStrength() {
29760     if (!nodes) return;
29761
29762     for (var i = 0, n = links.length; i < n; ++i) {
29763       strengths[i] = +strength(links[i], i, links);
29764     }
29765   }
29766
29767   function initializeDistance() {
29768     if (!nodes) return;
29769
29770     for (var i = 0, n = links.length; i < n; ++i) {
29771       distances[i] = +distance(links[i], i, links);
29772     }
29773   }
29774
29775   force.initialize = function(_) {
29776     nodes = _;
29777     initialize();
29778   };
29779
29780   force.links = function(_) {
29781     return arguments.length ? (links = _, initialize(), force) : links;
29782   };
29783
29784   force.id = function(_) {
29785     return arguments.length ? (id = _, force) : id;
29786   };
29787
29788   force.iterations = function(_) {
29789     return arguments.length ? (iterations = +_, force) : iterations;
29790   };
29791
29792   force.strength = function(_) {
29793     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initializeStrength(), force) : strength;
29794   };
29795
29796   force.distance = function(_) {
29797     return arguments.length ? (distance = typeof _ === "function" ? _ : constant$7(+_), initializeDistance(), force) : distance;
29798   };
29799
29800   return force;
29801 };
29802
29803 function x$2(d) {
29804   return d.x;
29805 }
29806
29807 function y$2(d) {
29808   return d.y;
29809 }
29810
29811 var initialRadius = 10;
29812 var initialAngle = Math.PI * (3 - Math.sqrt(5));
29813
29814 var simulation = function(nodes) {
29815   var simulation,
29816       alpha = 1,
29817       alphaMin = 0.001,
29818       alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
29819       alphaTarget = 0,
29820       velocityDecay = 0.6,
29821       forces = map$1(),
29822       stepper = timer(step),
29823       event = dispatch("tick", "end");
29824
29825   if (nodes == null) nodes = [];
29826
29827   function step() {
29828     tick();
29829     event.call("tick", simulation);
29830     if (alpha < alphaMin) {
29831       stepper.stop();
29832       event.call("end", simulation);
29833     }
29834   }
29835
29836   function tick() {
29837     var i, n = nodes.length, node;
29838
29839     alpha += (alphaTarget - alpha) * alphaDecay;
29840
29841     forces.each(function(force) {
29842       force(alpha);
29843     });
29844
29845     for (i = 0; i < n; ++i) {
29846       node = nodes[i];
29847       if (node.fx == null) node.x += node.vx *= velocityDecay;
29848       else node.x = node.fx, node.vx = 0;
29849       if (node.fy == null) node.y += node.vy *= velocityDecay;
29850       else node.y = node.fy, node.vy = 0;
29851     }
29852   }
29853
29854   function initializeNodes() {
29855     for (var i = 0, n = nodes.length, node; i < n; ++i) {
29856       node = nodes[i], node.index = i;
29857       if (isNaN(node.x) || isNaN(node.y)) {
29858         var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
29859         node.x = radius * Math.cos(angle);
29860         node.y = radius * Math.sin(angle);
29861       }
29862       if (isNaN(node.vx) || isNaN(node.vy)) {
29863         node.vx = node.vy = 0;
29864       }
29865     }
29866   }
29867
29868   function initializeForce(force) {
29869     if (force.initialize) force.initialize(nodes);
29870     return force;
29871   }
29872
29873   initializeNodes();
29874
29875   return simulation = {
29876     tick: tick,
29877
29878     restart: function() {
29879       return stepper.restart(step), simulation;
29880     },
29881
29882     stop: function() {
29883       return stepper.stop(), simulation;
29884     },
29885
29886     nodes: function(_) {
29887       return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
29888     },
29889
29890     alpha: function(_) {
29891       return arguments.length ? (alpha = +_, simulation) : alpha;
29892     },
29893
29894     alphaMin: function(_) {
29895       return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
29896     },
29897
29898     alphaDecay: function(_) {
29899       return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
29900     },
29901
29902     alphaTarget: function(_) {
29903       return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
29904     },
29905
29906     velocityDecay: function(_) {
29907       return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
29908     },
29909
29910     force: function(name, _) {
29911       return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
29912     },
29913
29914     find: function(x, y, radius) {
29915       var i = 0,
29916           n = nodes.length,
29917           dx,
29918           dy,
29919           d2,
29920           node,
29921           closest;
29922
29923       if (radius == null) radius = Infinity;
29924       else radius *= radius;
29925
29926       for (i = 0; i < n; ++i) {
29927         node = nodes[i];
29928         dx = x - node.x;
29929         dy = y - node.y;
29930         d2 = dx * dx + dy * dy;
29931         if (d2 < radius) closest = node, radius = d2;
29932       }
29933
29934       return closest;
29935     },
29936
29937     on: function(name, _) {
29938       return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
29939     }
29940   };
29941 };
29942
29943 var manyBody = function() {
29944   var nodes,
29945       node,
29946       alpha,
29947       strength = constant$7(-30),
29948       strengths,
29949       distanceMin2 = 1,
29950       distanceMax2 = Infinity,
29951       theta2 = 0.81;
29952
29953   function force(_) {
29954     var i, n = nodes.length, tree = quadtree(nodes, x$2, y$2).visitAfter(accumulate);
29955     for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
29956   }
29957
29958   function initialize() {
29959     if (!nodes) return;
29960     var i, n = nodes.length;
29961     strengths = new Array(n);
29962     for (i = 0; i < n; ++i) strengths[i] = +strength(nodes[i], i, nodes);
29963   }
29964
29965   function accumulate(quad) {
29966     var strength = 0, q, c, x$$1, y$$1, i;
29967
29968     // For internal nodes, accumulate forces from child quadrants.
29969     if (quad.length) {
29970       for (x$$1 = y$$1 = i = 0; i < 4; ++i) {
29971         if ((q = quad[i]) && (c = q.value)) {
29972           strength += c, x$$1 += c * q.x, y$$1 += c * q.y;
29973         }
29974       }
29975       quad.x = x$$1 / strength;
29976       quad.y = y$$1 / strength;
29977     }
29978
29979     // For leaf nodes, accumulate forces from coincident quadrants.
29980     else {
29981       q = quad;
29982       q.x = q.data.x;
29983       q.y = q.data.y;
29984       do strength += strengths[q.data.index];
29985       while (q = q.next);
29986     }
29987
29988     quad.value = strength;
29989   }
29990
29991   function apply(quad, x1, _, x2) {
29992     if (!quad.value) return true;
29993
29994     var x$$1 = quad.x - node.x,
29995         y$$1 = quad.y - node.y,
29996         w = x2 - x1,
29997         l = x$$1 * x$$1 + y$$1 * y$$1;
29998
29999     // Apply the Barnes-Hut approximation if possible.
30000     // Limit forces for very close nodes; randomize direction if coincident.
30001     if (w * w / theta2 < l) {
30002       if (l < distanceMax2) {
30003         if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
30004         if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
30005         if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
30006         node.vx += x$$1 * quad.value * alpha / l;
30007         node.vy += y$$1 * quad.value * alpha / l;
30008       }
30009       return true;
30010     }
30011
30012     // Otherwise, process points directly.
30013     else if (quad.length || l >= distanceMax2) return;
30014
30015     // Limit forces for very close nodes; randomize direction if coincident.
30016     if (quad.data !== node || quad.next) {
30017       if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
30018       if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
30019       if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
30020     }
30021
30022     do if (quad.data !== node) {
30023       w = strengths[quad.data.index] * alpha / l;
30024       node.vx += x$$1 * w;
30025       node.vy += y$$1 * w;
30026     } while (quad = quad.next);
30027   }
30028
30029   force.initialize = function(_) {
30030     nodes = _;
30031     initialize();
30032   };
30033
30034   force.strength = function(_) {
30035     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30036   };
30037
30038   force.distanceMin = function(_) {
30039     return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
30040   };
30041
30042   force.distanceMax = function(_) {
30043     return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
30044   };
30045
30046   force.theta = function(_) {
30047     return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
30048   };
30049
30050   return force;
30051 };
30052
30053 var x$3 = function(x) {
30054   var strength = constant$7(0.1),
30055       nodes,
30056       strengths,
30057       xz;
30058
30059   if (typeof x !== "function") x = constant$7(x == null ? 0 : +x);
30060
30061   function force(alpha) {
30062     for (var i = 0, n = nodes.length, node; i < n; ++i) {
30063       node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
30064     }
30065   }
30066
30067   function initialize() {
30068     if (!nodes) return;
30069     var i, n = nodes.length;
30070     strengths = new Array(n);
30071     xz = new Array(n);
30072     for (i = 0; i < n; ++i) {
30073       strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
30074     }
30075   }
30076
30077   force.initialize = function(_) {
30078     nodes = _;
30079     initialize();
30080   };
30081
30082   force.strength = function(_) {
30083     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30084   };
30085
30086   force.x = function(_) {
30087     return arguments.length ? (x = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : x;
30088   };
30089
30090   return force;
30091 };
30092
30093 var y$3 = function(y) {
30094   var strength = constant$7(0.1),
30095       nodes,
30096       strengths,
30097       yz;
30098
30099   if (typeof y !== "function") y = constant$7(y == null ? 0 : +y);
30100
30101   function force(alpha) {
30102     for (var i = 0, n = nodes.length, node; i < n; ++i) {
30103       node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
30104     }
30105   }
30106
30107   function initialize() {
30108     if (!nodes) return;
30109     var i, n = nodes.length;
30110     strengths = new Array(n);
30111     yz = new Array(n);
30112     for (i = 0; i < n; ++i) {
30113       strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
30114     }
30115   }
30116
30117   force.initialize = function(_) {
30118     nodes = _;
30119     initialize();
30120   };
30121
30122   force.strength = function(_) {
30123     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30124   };
30125
30126   force.y = function(_) {
30127     return arguments.length ? (y = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : y;
30128   };
30129
30130   return force;
30131 };
30132
30133 function nopropagation() {
30134   event.stopImmediatePropagation();
30135 }
30136
30137 var noevent = function() {
30138   event.preventDefault();
30139   event.stopImmediatePropagation();
30140 };
30141
30142 var dragDisable = function(view) {
30143   var root = view.document.documentElement,
30144       selection$$1 = select(view).on("dragstart.drag", noevent, true);
30145   if ("onselectstart" in root) {
30146     selection$$1.on("selectstart.drag", noevent, true);
30147   } else {
30148     root.__noselect = root.style.MozUserSelect;
30149     root.style.MozUserSelect = "none";
30150   }
30151 };
30152
30153 function yesdrag(view, noclick) {
30154   var root = view.document.documentElement,
30155       selection$$1 = select(view).on("dragstart.drag", null);
30156   if (noclick) {
30157     selection$$1.on("click.drag", noevent, true);
30158     setTimeout(function() { selection$$1.on("click.drag", null); }, 0);
30159   }
30160   if ("onselectstart" in root) {
30161     selection$$1.on("selectstart.drag", null);
30162   } else {
30163     root.style.MozUserSelect = root.__noselect;
30164     delete root.__noselect;
30165   }
30166 }
30167
30168 var constant$8 = function(x) {
30169   return function() {
30170     return x;
30171   };
30172 };
30173
30174 function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
30175   this.target = target;
30176   this.type = type;
30177   this.subject = subject;
30178   this.identifier = id;
30179   this.active = active;
30180   this.x = x;
30181   this.y = y;
30182   this.dx = dx;
30183   this.dy = dy;
30184   this._ = dispatch;
30185 }
30186
30187 DragEvent.prototype.on = function() {
30188   var value = this._.on.apply(this._, arguments);
30189   return value === this._ ? this : value;
30190 };
30191
30192 // Ignore right-click, since that should open the context menu.
30193 function defaultFilter() {
30194   return !event.button;
30195 }
30196
30197 function defaultContainer() {
30198   return this.parentNode;
30199 }
30200
30201 function defaultSubject(d) {
30202   return d == null ? {x: event.x, y: event.y} : d;
30203 }
30204
30205 var drag = function() {
30206   var filter = defaultFilter,
30207       container = defaultContainer,
30208       subject = defaultSubject,
30209       gestures = {},
30210       listeners = dispatch("start", "drag", "end"),
30211       active = 0,
30212       mousemoving,
30213       touchending;
30214
30215   function drag(selection$$1) {
30216     selection$$1
30217         .on("mousedown.drag", mousedowned)
30218         .on("touchstart.drag", touchstarted)
30219         .on("touchmove.drag", touchmoved)
30220         .on("touchend.drag touchcancel.drag", touchended)
30221         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
30222   }
30223
30224   function mousedowned() {
30225     if (touchending || !filter.apply(this, arguments)) return;
30226     var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
30227     if (!gesture) return;
30228     select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
30229     dragDisable(event.view);
30230     nopropagation();
30231     mousemoving = false;
30232     gesture("start");
30233   }
30234
30235   function mousemoved() {
30236     noevent();
30237     mousemoving = true;
30238     gestures.mouse("drag");
30239   }
30240
30241   function mouseupped() {
30242     select(event.view).on("mousemove.drag mouseup.drag", null);
30243     yesdrag(event.view, mousemoving);
30244     noevent();
30245     gestures.mouse("end");
30246   }
30247
30248   function touchstarted() {
30249     if (!filter.apply(this, arguments)) return;
30250     var touches$$1 = event.changedTouches,
30251         c = container.apply(this, arguments),
30252         n = touches$$1.length, i, gesture;
30253
30254     for (i = 0; i < n; ++i) {
30255       if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) {
30256         nopropagation();
30257         gesture("start");
30258       }
30259     }
30260   }
30261
30262   function touchmoved() {
30263     var touches$$1 = event.changedTouches,
30264         n = touches$$1.length, i, gesture;
30265
30266     for (i = 0; i < n; ++i) {
30267       if (gesture = gestures[touches$$1[i].identifier]) {
30268         noevent();
30269         gesture("drag");
30270       }
30271     }
30272   }
30273
30274   function touchended() {
30275     var touches$$1 = event.changedTouches,
30276         n = touches$$1.length, i, gesture;
30277
30278     if (touchending) clearTimeout(touchending);
30279     touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
30280     for (i = 0; i < n; ++i) {
30281       if (gesture = gestures[touches$$1[i].identifier]) {
30282         nopropagation();
30283         gesture("end");
30284       }
30285     }
30286   }
30287
30288   function beforestart(id, container, point, that, args) {
30289     var p = point(container, id), s, dx, dy,
30290         sublisteners = listeners.copy();
30291
30292     if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
30293       if ((event.subject = s = subject.apply(that, args)) == null) return false;
30294       dx = s.x - p[0] || 0;
30295       dy = s.y - p[1] || 0;
30296       return true;
30297     })) return;
30298
30299     return function gesture(type) {
30300       var p0 = p, n;
30301       switch (type) {
30302         case "start": gestures[id] = gesture, n = active++; break;
30303         case "end": delete gestures[id], --active; // nobreak
30304         case "drag": p = point(container, id), n = active; break;
30305       }
30306       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]);
30307     };
30308   }
30309
30310   drag.filter = function(_) {
30311     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$8(!!_), drag) : filter;
30312   };
30313
30314   drag.container = function(_) {
30315     return arguments.length ? (container = typeof _ === "function" ? _ : constant$8(_), drag) : container;
30316   };
30317
30318   drag.subject = function(_) {
30319     return arguments.length ? (subject = typeof _ === "function" ? _ : constant$8(_), drag) : subject;
30320   };
30321
30322   drag.on = function() {
30323     var value = listeners.on.apply(listeners, arguments);
30324     return value === listeners ? drag : value;
30325   };
30326
30327   return drag;
30328 };
30329
30330 var constant$9 = function(x) {
30331   return function() {
30332     return x;
30333   };
30334 };
30335
30336 function x$4(d) {
30337   return d[0];
30338 }
30339
30340 function y$4(d) {
30341   return d[1];
30342 }
30343
30344 function RedBlackTree() {
30345   this._ = null; // root node
30346 }
30347
30348 function RedBlackNode(node) {
30349   node.U = // parent node
30350   node.C = // color - true for red, false for black
30351   node.L = // left node
30352   node.R = // right node
30353   node.P = // previous node
30354   node.N = null; // next node
30355 }
30356
30357 RedBlackTree.prototype = {
30358   constructor: RedBlackTree,
30359
30360   insert: function(after, node) {
30361     var parent, grandpa, uncle;
30362
30363     if (after) {
30364       node.P = after;
30365       node.N = after.N;
30366       if (after.N) after.N.P = node;
30367       after.N = node;
30368       if (after.R) {
30369         after = after.R;
30370         while (after.L) after = after.L;
30371         after.L = node;
30372       } else {
30373         after.R = node;
30374       }
30375       parent = after;
30376     } else if (this._) {
30377       after = RedBlackFirst(this._);
30378       node.P = null;
30379       node.N = after;
30380       after.P = after.L = node;
30381       parent = after;
30382     } else {
30383       node.P = node.N = null;
30384       this._ = node;
30385       parent = null;
30386     }
30387     node.L = node.R = null;
30388     node.U = parent;
30389     node.C = true;
30390
30391     after = node;
30392     while (parent && parent.C) {
30393       grandpa = parent.U;
30394       if (parent === grandpa.L) {
30395         uncle = grandpa.R;
30396         if (uncle && uncle.C) {
30397           parent.C = uncle.C = false;
30398           grandpa.C = true;
30399           after = grandpa;
30400         } else {
30401           if (after === parent.R) {
30402             RedBlackRotateLeft(this, parent);
30403             after = parent;
30404             parent = after.U;
30405           }
30406           parent.C = false;
30407           grandpa.C = true;
30408           RedBlackRotateRight(this, grandpa);
30409         }
30410       } else {
30411         uncle = grandpa.L;
30412         if (uncle && uncle.C) {
30413           parent.C = uncle.C = false;
30414           grandpa.C = true;
30415           after = grandpa;
30416         } else {
30417           if (after === parent.L) {
30418             RedBlackRotateRight(this, parent);
30419             after = parent;
30420             parent = after.U;
30421           }
30422           parent.C = false;
30423           grandpa.C = true;
30424           RedBlackRotateLeft(this, grandpa);
30425         }
30426       }
30427       parent = after.U;
30428     }
30429     this._.C = false;
30430   },
30431
30432   remove: function(node) {
30433     if (node.N) node.N.P = node.P;
30434     if (node.P) node.P.N = node.N;
30435     node.N = node.P = null;
30436
30437     var parent = node.U,
30438         sibling,
30439         left = node.L,
30440         right = node.R,
30441         next,
30442         red;
30443
30444     if (!left) next = right;
30445     else if (!right) next = left;
30446     else next = RedBlackFirst(right);
30447
30448     if (parent) {
30449       if (parent.L === node) parent.L = next;
30450       else parent.R = next;
30451     } else {
30452       this._ = next;
30453     }
30454
30455     if (left && right) {
30456       red = next.C;
30457       next.C = node.C;
30458       next.L = left;
30459       left.U = next;
30460       if (next !== right) {
30461         parent = next.U;
30462         next.U = node.U;
30463         node = next.R;
30464         parent.L = node;
30465         next.R = right;
30466         right.U = next;
30467       } else {
30468         next.U = parent;
30469         parent = next;
30470         node = next.R;
30471       }
30472     } else {
30473       red = node.C;
30474       node = next;
30475     }
30476
30477     if (node) node.U = parent;
30478     if (red) return;
30479     if (node && node.C) { node.C = false; return; }
30480
30481     do {
30482       if (node === this._) break;
30483       if (node === parent.L) {
30484         sibling = parent.R;
30485         if (sibling.C) {
30486           sibling.C = false;
30487           parent.C = true;
30488           RedBlackRotateLeft(this, parent);
30489           sibling = parent.R;
30490         }
30491         if ((sibling.L && sibling.L.C)
30492             || (sibling.R && sibling.R.C)) {
30493           if (!sibling.R || !sibling.R.C) {
30494             sibling.L.C = false;
30495             sibling.C = true;
30496             RedBlackRotateRight(this, sibling);
30497             sibling = parent.R;
30498           }
30499           sibling.C = parent.C;
30500           parent.C = sibling.R.C = false;
30501           RedBlackRotateLeft(this, parent);
30502           node = this._;
30503           break;
30504         }
30505       } else {
30506         sibling = parent.L;
30507         if (sibling.C) {
30508           sibling.C = false;
30509           parent.C = true;
30510           RedBlackRotateRight(this, parent);
30511           sibling = parent.L;
30512         }
30513         if ((sibling.L && sibling.L.C)
30514           || (sibling.R && sibling.R.C)) {
30515           if (!sibling.L || !sibling.L.C) {
30516             sibling.R.C = false;
30517             sibling.C = true;
30518             RedBlackRotateLeft(this, sibling);
30519             sibling = parent.L;
30520           }
30521           sibling.C = parent.C;
30522           parent.C = sibling.L.C = false;
30523           RedBlackRotateRight(this, parent);
30524           node = this._;
30525           break;
30526         }
30527       }
30528       sibling.C = true;
30529       node = parent;
30530       parent = parent.U;
30531     } while (!node.C);
30532
30533     if (node) node.C = false;
30534   }
30535 };
30536
30537 function RedBlackRotateLeft(tree, node) {
30538   var p = node,
30539       q = node.R,
30540       parent = p.U;
30541
30542   if (parent) {
30543     if (parent.L === p) parent.L = q;
30544     else parent.R = q;
30545   } else {
30546     tree._ = q;
30547   }
30548
30549   q.U = parent;
30550   p.U = q;
30551   p.R = q.L;
30552   if (p.R) p.R.U = p;
30553   q.L = p;
30554 }
30555
30556 function RedBlackRotateRight(tree, node) {
30557   var p = node,
30558       q = node.L,
30559       parent = p.U;
30560
30561   if (parent) {
30562     if (parent.L === p) parent.L = q;
30563     else parent.R = q;
30564   } else {
30565     tree._ = q;
30566   }
30567
30568   q.U = parent;
30569   p.U = q;
30570   p.L = q.R;
30571   if (p.L) p.L.U = p;
30572   q.R = p;
30573 }
30574
30575 function RedBlackFirst(node) {
30576   while (node.L) node = node.L;
30577   return node;
30578 }
30579
30580 function createEdge(left, right, v0, v1) {
30581   var edge = [null, null],
30582       index = edges.push(edge) - 1;
30583   edge.left = left;
30584   edge.right = right;
30585   if (v0) setEdgeEnd(edge, left, right, v0);
30586   if (v1) setEdgeEnd(edge, right, left, v1);
30587   cells[left.index].halfedges.push(index);
30588   cells[right.index].halfedges.push(index);
30589   return edge;
30590 }
30591
30592 function createBorderEdge(left, v0, v1) {
30593   var edge = [v0, v1];
30594   edge.left = left;
30595   return edge;
30596 }
30597
30598 function setEdgeEnd(edge, left, right, vertex) {
30599   if (!edge[0] && !edge[1]) {
30600     edge[0] = vertex;
30601     edge.left = left;
30602     edge.right = right;
30603   } else if (edge.left === right) {
30604     edge[1] = vertex;
30605   } else {
30606     edge[0] = vertex;
30607   }
30608 }
30609
30610 // Liang–Barsky line clipping.
30611 function clipEdge(edge, x0, y0, x1, y1) {
30612   var a = edge[0],
30613       b = edge[1],
30614       ax = a[0],
30615       ay = a[1],
30616       bx = b[0],
30617       by = b[1],
30618       t0 = 0,
30619       t1 = 1,
30620       dx = bx - ax,
30621       dy = by - ay,
30622       r;
30623
30624   r = x0 - ax;
30625   if (!dx && r > 0) return;
30626   r /= dx;
30627   if (dx < 0) {
30628     if (r < t0) return;
30629     if (r < t1) t1 = r;
30630   } else if (dx > 0) {
30631     if (r > t1) return;
30632     if (r > t0) t0 = r;
30633   }
30634
30635   r = x1 - ax;
30636   if (!dx && r < 0) return;
30637   r /= dx;
30638   if (dx < 0) {
30639     if (r > t1) return;
30640     if (r > t0) t0 = r;
30641   } else if (dx > 0) {
30642     if (r < t0) return;
30643     if (r < t1) t1 = r;
30644   }
30645
30646   r = y0 - ay;
30647   if (!dy && r > 0) return;
30648   r /= dy;
30649   if (dy < 0) {
30650     if (r < t0) return;
30651     if (r < t1) t1 = r;
30652   } else if (dy > 0) {
30653     if (r > t1) return;
30654     if (r > t0) t0 = r;
30655   }
30656
30657   r = y1 - ay;
30658   if (!dy && r < 0) return;
30659   r /= dy;
30660   if (dy < 0) {
30661     if (r > t1) return;
30662     if (r > t0) t0 = r;
30663   } else if (dy > 0) {
30664     if (r < t0) return;
30665     if (r < t1) t1 = r;
30666   }
30667
30668   if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
30669
30670   if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
30671   if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
30672   return true;
30673 }
30674
30675 function connectEdge(edge, x0, y0, x1, y1) {
30676   var v1 = edge[1];
30677   if (v1) return true;
30678
30679   var v0 = edge[0],
30680       left = edge.left,
30681       right = edge.right,
30682       lx = left[0],
30683       ly = left[1],
30684       rx = right[0],
30685       ry = right[1],
30686       fx = (lx + rx) / 2,
30687       fy = (ly + ry) / 2,
30688       fm,
30689       fb;
30690
30691   if (ry === ly) {
30692     if (fx < x0 || fx >= x1) return;
30693     if (lx > rx) {
30694       if (!v0) v0 = [fx, y0];
30695       else if (v0[1] >= y1) return;
30696       v1 = [fx, y1];
30697     } else {
30698       if (!v0) v0 = [fx, y1];
30699       else if (v0[1] < y0) return;
30700       v1 = [fx, y0];
30701     }
30702   } else {
30703     fm = (lx - rx) / (ry - ly);
30704     fb = fy - fm * fx;
30705     if (fm < -1 || fm > 1) {
30706       if (lx > rx) {
30707         if (!v0) v0 = [(y0 - fb) / fm, y0];
30708         else if (v0[1] >= y1) return;
30709         v1 = [(y1 - fb) / fm, y1];
30710       } else {
30711         if (!v0) v0 = [(y1 - fb) / fm, y1];
30712         else if (v0[1] < y0) return;
30713         v1 = [(y0 - fb) / fm, y0];
30714       }
30715     } else {
30716       if (ly < ry) {
30717         if (!v0) v0 = [x0, fm * x0 + fb];
30718         else if (v0[0] >= x1) return;
30719         v1 = [x1, fm * x1 + fb];
30720       } else {
30721         if (!v0) v0 = [x1, fm * x1 + fb];
30722         else if (v0[0] < x0) return;
30723         v1 = [x0, fm * x0 + fb];
30724       }
30725     }
30726   }
30727
30728   edge[0] = v0;
30729   edge[1] = v1;
30730   return true;
30731 }
30732
30733 function clipEdges(x0, y0, x1, y1) {
30734   var i = edges.length,
30735       edge;
30736
30737   while (i--) {
30738     if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
30739         || !clipEdge(edge, x0, y0, x1, y1)
30740         || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$3
30741             || Math.abs(edge[0][1] - edge[1][1]) > epsilon$3)) {
30742       delete edges[i];
30743     }
30744   }
30745 }
30746
30747 function createCell(site) {
30748   return cells[site.index] = {
30749     site: site,
30750     halfedges: []
30751   };
30752 }
30753
30754 function cellHalfedgeAngle(cell, edge) {
30755   var site = cell.site,
30756       va = edge.left,
30757       vb = edge.right;
30758   if (site === vb) vb = va, va = site;
30759   if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
30760   if (site === va) va = edge[1], vb = edge[0];
30761   else va = edge[0], vb = edge[1];
30762   return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
30763 }
30764
30765 function cellHalfedgeStart(cell, edge) {
30766   return edge[+(edge.left !== cell.site)];
30767 }
30768
30769 function cellHalfedgeEnd(cell, edge) {
30770   return edge[+(edge.left === cell.site)];
30771 }
30772
30773 function sortCellHalfedges() {
30774   for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
30775     if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
30776       var index = new Array(m),
30777           array = new Array(m);
30778       for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
30779       index.sort(function(i, j) { return array[j] - array[i]; });
30780       for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
30781       for (j = 0; j < m; ++j) halfedges[j] = array[j];
30782     }
30783   }
30784 }
30785
30786 function clipCells(x0, y0, x1, y1) {
30787   var nCells = cells.length,
30788       iCell,
30789       cell,
30790       site,
30791       iHalfedge,
30792       halfedges,
30793       nHalfedges,
30794       start,
30795       startX,
30796       startY,
30797       end,
30798       endX,
30799       endY,
30800       cover = true;
30801
30802   for (iCell = 0; iCell < nCells; ++iCell) {
30803     if (cell = cells[iCell]) {
30804       site = cell.site;
30805       halfedges = cell.halfedges;
30806       iHalfedge = halfedges.length;
30807
30808       // Remove any dangling clipped edges.
30809       while (iHalfedge--) {
30810         if (!edges[halfedges[iHalfedge]]) {
30811           halfedges.splice(iHalfedge, 1);
30812         }
30813       }
30814
30815       // Insert any border edges as necessary.
30816       iHalfedge = 0, nHalfedges = halfedges.length;
30817       while (iHalfedge < nHalfedges) {
30818         end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
30819         start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
30820         if (Math.abs(endX - startX) > epsilon$3 || Math.abs(endY - startY) > epsilon$3) {
30821           halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
30822               Math.abs(endX - x0) < epsilon$3 && y1 - endY > epsilon$3 ? [x0, Math.abs(startX - x0) < epsilon$3 ? startY : y1]
30823               : Math.abs(endY - y1) < epsilon$3 && x1 - endX > epsilon$3 ? [Math.abs(startY - y1) < epsilon$3 ? startX : x1, y1]
30824               : Math.abs(endX - x1) < epsilon$3 && endY - y0 > epsilon$3 ? [x1, Math.abs(startX - x1) < epsilon$3 ? startY : y0]
30825               : Math.abs(endY - y0) < epsilon$3 && endX - x0 > epsilon$3 ? [Math.abs(startY - y0) < epsilon$3 ? startX : x0, y0]
30826               : null)) - 1);
30827           ++nHalfedges;
30828         }
30829       }
30830
30831       if (nHalfedges) cover = false;
30832     }
30833   }
30834
30835   // If there weren’t any edges, have the closest site cover the extent.
30836   // It doesn’t matter which corner of the extent we measure!
30837   if (cover) {
30838     var dx, dy, d2, dc = Infinity;
30839
30840     for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
30841       if (cell = cells[iCell]) {
30842         site = cell.site;
30843         dx = site[0] - x0;
30844         dy = site[1] - y0;
30845         d2 = dx * dx + dy * dy;
30846         if (d2 < dc) dc = d2, cover = cell;
30847       }
30848     }
30849
30850     if (cover) {
30851       var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
30852       cover.halfedges.push(
30853         edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
30854         edges.push(createBorderEdge(site, v01, v11)) - 1,
30855         edges.push(createBorderEdge(site, v11, v10)) - 1,
30856         edges.push(createBorderEdge(site, v10, v00)) - 1
30857       );
30858     }
30859   }
30860
30861   // Lastly delete any cells with no edges; these were entirely clipped.
30862   for (iCell = 0; iCell < nCells; ++iCell) {
30863     if (cell = cells[iCell]) {
30864       if (!cell.halfedges.length) {
30865         delete cells[iCell];
30866       }
30867     }
30868   }
30869 }
30870
30871 var circlePool = [];
30872
30873 var firstCircle;
30874
30875 function Circle() {
30876   RedBlackNode(this);
30877   this.x =
30878   this.y =
30879   this.arc =
30880   this.site =
30881   this.cy = null;
30882 }
30883
30884 function attachCircle(arc) {
30885   var lArc = arc.P,
30886       rArc = arc.N;
30887
30888   if (!lArc || !rArc) return;
30889
30890   var lSite = lArc.site,
30891       cSite = arc.site,
30892       rSite = rArc.site;
30893
30894   if (lSite === rSite) return;
30895
30896   var bx = cSite[0],
30897       by = cSite[1],
30898       ax = lSite[0] - bx,
30899       ay = lSite[1] - by,
30900       cx = rSite[0] - bx,
30901       cy = rSite[1] - by;
30902
30903   var d = 2 * (ax * cy - ay * cx);
30904   if (d >= -epsilon2$1) return;
30905
30906   var ha = ax * ax + ay * ay,
30907       hc = cx * cx + cy * cy,
30908       x = (cy * ha - ay * hc) / d,
30909       y = (ax * hc - cx * ha) / d;
30910
30911   var circle = circlePool.pop() || new Circle;
30912   circle.arc = arc;
30913   circle.site = cSite;
30914   circle.x = x + bx;
30915   circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
30916
30917   arc.circle = circle;
30918
30919   var before = null,
30920       node = circles._;
30921
30922   while (node) {
30923     if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
30924       if (node.L) node = node.L;
30925       else { before = node.P; break; }
30926     } else {
30927       if (node.R) node = node.R;
30928       else { before = node; break; }
30929     }
30930   }
30931
30932   circles.insert(before, circle);
30933   if (!before) firstCircle = circle;
30934 }
30935
30936 function detachCircle(arc) {
30937   var circle = arc.circle;
30938   if (circle) {
30939     if (!circle.P) firstCircle = circle.N;
30940     circles.remove(circle);
30941     circlePool.push(circle);
30942     RedBlackNode(circle);
30943     arc.circle = null;
30944   }
30945 }
30946
30947 var beachPool = [];
30948
30949 function Beach() {
30950   RedBlackNode(this);
30951   this.edge =
30952   this.site =
30953   this.circle = null;
30954 }
30955
30956 function createBeach(site) {
30957   var beach = beachPool.pop() || new Beach;
30958   beach.site = site;
30959   return beach;
30960 }
30961
30962 function detachBeach(beach) {
30963   detachCircle(beach);
30964   beaches.remove(beach);
30965   beachPool.push(beach);
30966   RedBlackNode(beach);
30967 }
30968
30969 function removeBeach(beach) {
30970   var circle = beach.circle,
30971       x = circle.x,
30972       y = circle.cy,
30973       vertex = [x, y],
30974       previous = beach.P,
30975       next = beach.N,
30976       disappearing = [beach];
30977
30978   detachBeach(beach);
30979
30980   var lArc = previous;
30981   while (lArc.circle
30982       && Math.abs(x - lArc.circle.x) < epsilon$3
30983       && Math.abs(y - lArc.circle.cy) < epsilon$3) {
30984     previous = lArc.P;
30985     disappearing.unshift(lArc);
30986     detachBeach(lArc);
30987     lArc = previous;
30988   }
30989
30990   disappearing.unshift(lArc);
30991   detachCircle(lArc);
30992
30993   var rArc = next;
30994   while (rArc.circle
30995       && Math.abs(x - rArc.circle.x) < epsilon$3
30996       && Math.abs(y - rArc.circle.cy) < epsilon$3) {
30997     next = rArc.N;
30998     disappearing.push(rArc);
30999     detachBeach(rArc);
31000     rArc = next;
31001   }
31002
31003   disappearing.push(rArc);
31004   detachCircle(rArc);
31005
31006   var nArcs = disappearing.length,
31007       iArc;
31008   for (iArc = 1; iArc < nArcs; ++iArc) {
31009     rArc = disappearing[iArc];
31010     lArc = disappearing[iArc - 1];
31011     setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
31012   }
31013
31014   lArc = disappearing[0];
31015   rArc = disappearing[nArcs - 1];
31016   rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
31017
31018   attachCircle(lArc);
31019   attachCircle(rArc);
31020 }
31021
31022 function addBeach(site) {
31023   var x = site[0],
31024       directrix = site[1],
31025       lArc,
31026       rArc,
31027       dxl,
31028       dxr,
31029       node = beaches._;
31030
31031   while (node) {
31032     dxl = leftBreakPoint(node, directrix) - x;
31033     if (dxl > epsilon$3) node = node.L; else {
31034       dxr = x - rightBreakPoint(node, directrix);
31035       if (dxr > epsilon$3) {
31036         if (!node.R) {
31037           lArc = node;
31038           break;
31039         }
31040         node = node.R;
31041       } else {
31042         if (dxl > -epsilon$3) {
31043           lArc = node.P;
31044           rArc = node;
31045         } else if (dxr > -epsilon$3) {
31046           lArc = node;
31047           rArc = node.N;
31048         } else {
31049           lArc = rArc = node;
31050         }
31051         break;
31052       }
31053     }
31054   }
31055
31056   createCell(site);
31057   var newArc = createBeach(site);
31058   beaches.insert(lArc, newArc);
31059
31060   if (!lArc && !rArc) return;
31061
31062   if (lArc === rArc) {
31063     detachCircle(lArc);
31064     rArc = createBeach(lArc.site);
31065     beaches.insert(newArc, rArc);
31066     newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
31067     attachCircle(lArc);
31068     attachCircle(rArc);
31069     return;
31070   }
31071
31072   if (!rArc) { // && lArc
31073     newArc.edge = createEdge(lArc.site, newArc.site);
31074     return;
31075   }
31076
31077   // else lArc !== rArc
31078   detachCircle(lArc);
31079   detachCircle(rArc);
31080
31081   var lSite = lArc.site,
31082       ax = lSite[0],
31083       ay = lSite[1],
31084       bx = site[0] - ax,
31085       by = site[1] - ay,
31086       rSite = rArc.site,
31087       cx = rSite[0] - ax,
31088       cy = rSite[1] - ay,
31089       d = 2 * (bx * cy - by * cx),
31090       hb = bx * bx + by * by,
31091       hc = cx * cx + cy * cy,
31092       vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
31093
31094   setEdgeEnd(rArc.edge, lSite, rSite, vertex);
31095   newArc.edge = createEdge(lSite, site, null, vertex);
31096   rArc.edge = createEdge(site, rSite, null, vertex);
31097   attachCircle(lArc);
31098   attachCircle(rArc);
31099 }
31100
31101 function leftBreakPoint(arc, directrix) {
31102   var site = arc.site,
31103       rfocx = site[0],
31104       rfocy = site[1],
31105       pby2 = rfocy - directrix;
31106
31107   if (!pby2) return rfocx;
31108
31109   var lArc = arc.P;
31110   if (!lArc) return -Infinity;
31111
31112   site = lArc.site;
31113   var lfocx = site[0],
31114       lfocy = site[1],
31115       plby2 = lfocy - directrix;
31116
31117   if (!plby2) return lfocx;
31118
31119   var hl = lfocx - rfocx,
31120       aby2 = 1 / pby2 - 1 / plby2,
31121       b = hl / plby2;
31122
31123   if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
31124
31125   return (rfocx + lfocx) / 2;
31126 }
31127
31128 function rightBreakPoint(arc, directrix) {
31129   var rArc = arc.N;
31130   if (rArc) return leftBreakPoint(rArc, directrix);
31131   var site = arc.site;
31132   return site[1] === directrix ? site[0] : Infinity;
31133 }
31134
31135 var epsilon$3 = 1e-6;
31136 var epsilon2$1 = 1e-12;
31137 var beaches;
31138 var cells;
31139 var circles;
31140 var edges;
31141
31142 function triangleArea(a, b, c) {
31143   return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
31144 }
31145
31146 function lexicographic(a, b) {
31147   return b[1] - a[1]
31148       || b[0] - a[0];
31149 }
31150
31151 function Diagram(sites, extent) {
31152   var site = sites.sort(lexicographic).pop(),
31153       x,
31154       y,
31155       circle;
31156
31157   edges = [];
31158   cells = new Array(sites.length);
31159   beaches = new RedBlackTree;
31160   circles = new RedBlackTree;
31161
31162   while (true) {
31163     circle = firstCircle;
31164     if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
31165       if (site[0] !== x || site[1] !== y) {
31166         addBeach(site);
31167         x = site[0], y = site[1];
31168       }
31169       site = sites.pop();
31170     } else if (circle) {
31171       removeBeach(circle.arc);
31172     } else {
31173       break;
31174     }
31175   }
31176
31177   sortCellHalfedges();
31178
31179   if (extent) {
31180     var x0 = +extent[0][0],
31181         y0 = +extent[0][1],
31182         x1 = +extent[1][0],
31183         y1 = +extent[1][1];
31184     clipEdges(x0, y0, x1, y1);
31185     clipCells(x0, y0, x1, y1);
31186   }
31187
31188   this.edges = edges;
31189   this.cells = cells;
31190
31191   beaches =
31192   circles =
31193   edges =
31194   cells = null;
31195 }
31196
31197 Diagram.prototype = {
31198   constructor: Diagram,
31199
31200   polygons: function() {
31201     var edges = this.edges;
31202
31203     return this.cells.map(function(cell) {
31204       var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
31205       polygon.data = cell.site.data;
31206       return polygon;
31207     });
31208   },
31209
31210   triangles: function() {
31211     var triangles = [],
31212         edges = this.edges;
31213
31214     this.cells.forEach(function(cell, i) {
31215       var site = cell.site,
31216           halfedges = cell.halfedges,
31217           j = -1,
31218           m = halfedges.length,
31219           s0,
31220           e1 = edges[halfedges[m - 1]],
31221           s1 = e1.left === site ? e1.right : e1.left;
31222
31223       while (++j < m) {
31224         s0 = s1;
31225         e1 = edges[halfedges[j]];
31226         s1 = e1.left === site ? e1.right : e1.left;
31227         if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
31228           triangles.push([site.data, s0.data, s1.data]);
31229         }
31230       }
31231     });
31232
31233     return triangles;
31234   },
31235
31236   links: function() {
31237     return this.edges.filter(function(edge) {
31238       return edge.right;
31239     }).map(function(edge) {
31240       return {
31241         source: edge.left.data,
31242         target: edge.right.data
31243       };
31244     });
31245   },
31246
31247   find: function(x, y, radius) {
31248     var that = this,
31249         i0, i1 = that._found || 0,
31250         cell = that.cells[i1] || that.cells[i1 = 0],
31251         dx = x - cell.site[0],
31252         dy = y - cell.site[1],
31253         d2 = dx * dx + dy * dy;
31254
31255     do {
31256       cell = that.cells[i0 = i1], i1 = null;
31257       cell.halfedges.forEach(function(e) {
31258         var edge = that.edges[e], v = edge.left;
31259         if ((v === cell.site || !v) && !(v = edge.right)) return;
31260         var vx = x - v[0],
31261             vy = y - v[1],
31262             v2 = vx * vx + vy * vy;
31263         if (v2 < d2) d2 = v2, i1 = v.index;
31264       });
31265     } while (i1 !== null);
31266
31267     that._found = i0;
31268
31269     return radius == null || d2 <= radius * radius ? cell.site : null;
31270   }
31271 };
31272
31273 var voronoi = function() {
31274   var x$$1 = x$4,
31275       y$$1 = y$4,
31276       extent = null;
31277
31278   function voronoi(data) {
31279     return new Diagram(data.map(function(d, i) {
31280       var s = [Math.round(x$$1(d, i, data) / epsilon$3) * epsilon$3, Math.round(y$$1(d, i, data) / epsilon$3) * epsilon$3];
31281       s.index = i;
31282       s.data = d;
31283       return s;
31284     }), extent);
31285   }
31286
31287   voronoi.polygons = function(data) {
31288     return voronoi(data).polygons();
31289   };
31290
31291   voronoi.links = function(data) {
31292     return voronoi(data).links();
31293   };
31294
31295   voronoi.triangles = function(data) {
31296     return voronoi(data).triangles();
31297   };
31298
31299   voronoi.x = function(_) {
31300     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : x$$1;
31301   };
31302
31303   voronoi.y = function(_) {
31304     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : y$$1;
31305   };
31306
31307   voronoi.extent = function(_) {
31308     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]]];
31309   };
31310
31311   voronoi.size = function(_) {
31312     return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
31313   };
31314
31315   return voronoi;
31316 };
31317
31318 var constant$10 = function(x) {
31319   return function() {
31320     return x;
31321   };
31322 };
31323
31324 function ZoomEvent(target, type, transform) {
31325   this.target = target;
31326   this.type = type;
31327   this.transform = transform;
31328 }
31329
31330 function Transform(k, x, y) {
31331   this.k = k;
31332   this.x = x;
31333   this.y = y;
31334 }
31335
31336 Transform.prototype = {
31337   constructor: Transform,
31338   scale: function(k) {
31339     return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
31340   },
31341   translate: function(x, y) {
31342     return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
31343   },
31344   apply: function(point) {
31345     return [point[0] * this.k + this.x, point[1] * this.k + this.y];
31346   },
31347   applyX: function(x) {
31348     return x * this.k + this.x;
31349   },
31350   applyY: function(y) {
31351     return y * this.k + this.y;
31352   },
31353   invert: function(location) {
31354     return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
31355   },
31356   invertX: function(x) {
31357     return (x - this.x) / this.k;
31358   },
31359   invertY: function(y) {
31360     return (y - this.y) / this.k;
31361   },
31362   rescaleX: function(x) {
31363     return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
31364   },
31365   rescaleY: function(y) {
31366     return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
31367   },
31368   toString: function() {
31369     return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
31370   }
31371 };
31372
31373 var identity$6 = new Transform(1, 0, 0);
31374
31375 transform.prototype = Transform.prototype;
31376
31377 function transform(node) {
31378   return node.__zoom || identity$6;
31379 }
31380
31381 function nopropagation$1() {
31382   event.stopImmediatePropagation();
31383 }
31384
31385 var noevent$1 = function() {
31386   event.preventDefault();
31387   event.stopImmediatePropagation();
31388 };
31389
31390 // Ignore right-click, since that should open the context menu.
31391 function defaultFilter$1() {
31392   return !event.button;
31393 }
31394
31395 function defaultExtent() {
31396   var e = this, w, h;
31397   if (e instanceof SVGElement) {
31398     e = e.ownerSVGElement || e;
31399     w = e.width.baseVal.value;
31400     h = e.height.baseVal.value;
31401   } else {
31402     w = e.clientWidth;
31403     h = e.clientHeight;
31404   }
31405   return [[0, 0], [w, h]];
31406 }
31407
31408 function defaultTransform() {
31409   return this.__zoom || identity$6;
31410 }
31411
31412 var zoom = function() {
31413   var filter = defaultFilter$1,
31414       extent = defaultExtent,
31415       k0 = 0,
31416       k1 = Infinity,
31417       x0 = -k1,
31418       x1 = k1,
31419       y0 = x0,
31420       y1 = x1,
31421       duration = 250,
31422       gestures = [],
31423       listeners = dispatch("start", "zoom", "end"),
31424       touchstarting,
31425       touchending,
31426       touchDelay = 500,
31427       wheelDelay = 150;
31428
31429   function zoom(selection$$1) {
31430     selection$$1
31431         .on("wheel.zoom", wheeled)
31432         .on("mousedown.zoom", mousedowned)
31433         .on("dblclick.zoom", dblclicked)
31434         .on("touchstart.zoom", touchstarted)
31435         .on("touchmove.zoom", touchmoved)
31436         .on("touchend.zoom touchcancel.zoom", touchended)
31437         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
31438         .property("__zoom", defaultTransform);
31439   }
31440
31441   zoom.transform = function(collection, transform) {
31442     var selection$$1 = collection.selection ? collection.selection() : collection;
31443     selection$$1.property("__zoom", defaultTransform);
31444     if (collection !== selection$$1) {
31445       schedule(collection, transform);
31446     } else {
31447       selection$$1.interrupt().each(function() {
31448         gesture(this, arguments)
31449             .start()
31450             .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform)
31451             .end();
31452       });
31453     }
31454   };
31455
31456   zoom.scaleBy = function(selection$$1, k) {
31457     zoom.scaleTo(selection$$1, function() {
31458       var k0 = this.__zoom.k,
31459           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
31460       return k0 * k1;
31461     });
31462   };
31463
31464   zoom.scaleTo = function(selection$$1, k) {
31465     zoom.transform(selection$$1, function() {
31466       var e = extent.apply(this, arguments),
31467           t0 = this.__zoom,
31468           p0 = centroid(e),
31469           p1 = t0.invert(p0),
31470           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
31471       return constrain(translate(scale(t0, k1), p0, p1), e);
31472     });
31473   };
31474
31475   zoom.translateBy = function(selection$$1, x, y) {
31476     zoom.transform(selection$$1, function() {
31477       return constrain(this.__zoom.translate(
31478         typeof x === "function" ? x.apply(this, arguments) : x,
31479         typeof y === "function" ? y.apply(this, arguments) : y
31480       ), extent.apply(this, arguments));
31481     });
31482   };
31483
31484   function scale(transform, k) {
31485     k = Math.max(k0, Math.min(k1, k));
31486     return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
31487   }
31488
31489   function translate(transform, p0, p1) {
31490     var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k;
31491     return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
31492   }
31493
31494   function constrain(transform, extent) {
31495     var dx = Math.min(0, transform.invertX(extent[0][0]) - x0) || Math.max(0, transform.invertX(extent[1][0]) - x1),
31496         dy = Math.min(0, transform.invertY(extent[0][1]) - y0) || Math.max(0, transform.invertY(extent[1][1]) - y1);
31497     return dx || dy ? transform.translate(dx, dy) : transform;
31498   }
31499
31500   function centroid(extent) {
31501     return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
31502   }
31503
31504   function schedule(transition$$1, transform, center) {
31505     transition$$1
31506         .on("start.zoom", function() { gesture(this, arguments).start(); })
31507         .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
31508         .tween("zoom", function() {
31509           var that = this,
31510               args = arguments,
31511               g = gesture(that, args),
31512               e = extent.apply(that, args),
31513               p = center || centroid(e),
31514               w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
31515               a = that.__zoom,
31516               b = typeof transform === "function" ? transform.apply(that, args) : transform,
31517               i = interpolateZoom(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
31518           return function(t) {
31519             if (t === 1) t = b; // Avoid rounding error on end.
31520             else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
31521             g.zoom(null, t);
31522           };
31523         });
31524   }
31525
31526   function gesture(that, args) {
31527     for (var i = 0, n = gestures.length, g; i < n; ++i) {
31528       if ((g = gestures[i]).that === that) {
31529         return g;
31530       }
31531     }
31532     return new Gesture(that, args);
31533   }
31534
31535   function Gesture(that, args) {
31536     this.that = that;
31537     this.args = args;
31538     this.index = -1;
31539     this.active = 0;
31540     this.extent = extent.apply(that, args);
31541   }
31542
31543   Gesture.prototype = {
31544     start: function() {
31545       if (++this.active === 1) {
31546         this.index = gestures.push(this) - 1;
31547         this.emit("start");
31548       }
31549       return this;
31550     },
31551     zoom: function(key, transform) {
31552       if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
31553       if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
31554       if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
31555       this.that.__zoom = transform;
31556       this.emit("zoom");
31557       return this;
31558     },
31559     end: function() {
31560       if (--this.active === 0) {
31561         gestures.splice(this.index, 1);
31562         this.index = -1;
31563         this.emit("end");
31564       }
31565       return this;
31566     },
31567     emit: function(type) {
31568       customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
31569     }
31570   };
31571
31572   function wheeled() {
31573     if (!filter.apply(this, arguments)) return;
31574     var g = gesture(this, arguments),
31575         t = this.__zoom,
31576         k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))),
31577         p = mouse(this);
31578
31579     // If the mouse is in the same location as before, reuse it.
31580     // If there were recent wheel events, reset the wheel idle timeout.
31581     if (g.wheel) {
31582       if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
31583         g.mouse[1] = t.invert(g.mouse[0] = p);
31584       }
31585       clearTimeout(g.wheel);
31586     }
31587
31588     // If this wheel event won’t trigger a transform change, ignore it.
31589     else if (t.k === k) return;
31590
31591     // Otherwise, capture the mouse point and location at the start.
31592     else {
31593       g.mouse = [p, t.invert(p)];
31594       interrupt(this);
31595       g.start();
31596     }
31597
31598     noevent$1();
31599     g.wheel = setTimeout(wheelidled, wheelDelay);
31600     g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent));
31601
31602     function wheelidled() {
31603       g.wheel = null;
31604       g.end();
31605     }
31606   }
31607
31608   function mousedowned() {
31609     if (touchending || !filter.apply(this, arguments)) return;
31610     var g = gesture(this, arguments),
31611         v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
31612         p = mouse(this);
31613
31614     dragDisable(event.view);
31615     nopropagation$1();
31616     g.mouse = [p, this.__zoom.invert(p)];
31617     interrupt(this);
31618     g.start();
31619
31620     function mousemoved() {
31621       noevent$1();
31622       g.moved = true;
31623       g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent));
31624     }
31625
31626     function mouseupped() {
31627       v.on("mousemove.zoom mouseup.zoom", null);
31628       yesdrag(event.view, g.moved);
31629       noevent$1();
31630       g.end();
31631     }
31632   }
31633
31634   function dblclicked() {
31635     if (!filter.apply(this, arguments)) return;
31636     var t0 = this.__zoom,
31637         p0 = mouse(this),
31638         p1 = t0.invert(p0),
31639         k1 = t0.k * (event.shiftKey ? 0.5 : 2),
31640         t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments));
31641
31642     noevent$1();
31643     if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
31644     else select(this).call(zoom.transform, t1);
31645   }
31646
31647   function touchstarted() {
31648     if (!filter.apply(this, arguments)) return;
31649     var g = gesture(this, arguments),
31650         touches$$1 = event.changedTouches,
31651         n = touches$$1.length, i, t, p;
31652
31653     nopropagation$1();
31654     for (i = 0; i < n; ++i) {
31655       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
31656       p = [p, this.__zoom.invert(p), t.identifier];
31657       if (!g.touch0) g.touch0 = p;
31658       else if (!g.touch1) g.touch1 = p;
31659     }
31660     if (touchstarting) {
31661       touchstarting = clearTimeout(touchstarting);
31662       if (!g.touch1) return g.end(), dblclicked.apply(this, arguments);
31663     }
31664     if (event.touches.length === n) {
31665       touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
31666       interrupt(this);
31667       g.start();
31668     }
31669   }
31670
31671   function touchmoved() {
31672     var g = gesture(this, arguments),
31673         touches$$1 = event.changedTouches,
31674         n = touches$$1.length, i, t, p, l;
31675
31676     noevent$1();
31677     if (touchstarting) touchstarting = clearTimeout(touchstarting);
31678     for (i = 0; i < n; ++i) {
31679       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
31680       if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
31681       else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
31682     }
31683     t = g.that.__zoom;
31684     if (g.touch1) {
31685       var p0 = g.touch0[0], l0 = g.touch0[1],
31686           p1 = g.touch1[0], l1 = g.touch1[1],
31687           dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
31688           dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
31689       t = scale(t, Math.sqrt(dp / dl));
31690       p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
31691       l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
31692     }
31693     else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
31694     else return;
31695     g.zoom("touch", constrain(translate(t, p, l), g.extent));
31696   }
31697
31698   function touchended() {
31699     var g = gesture(this, arguments),
31700         touches$$1 = event.changedTouches,
31701         n = touches$$1.length, i, t;
31702
31703     nopropagation$1();
31704     if (touchending) clearTimeout(touchending);
31705     touchending = setTimeout(function() { touchending = null; }, touchDelay);
31706     for (i = 0; i < n; ++i) {
31707       t = touches$$1[i];
31708       if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
31709       else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
31710     }
31711     if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
31712     if (!g.touch0) g.end();
31713   }
31714
31715   zoom.filter = function(_) {
31716     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$10(!!_), zoom) : filter;
31717   };
31718
31719   zoom.extent = function(_) {
31720     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$10([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
31721   };
31722
31723   zoom.scaleExtent = function(_) {
31724     return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1];
31725   };
31726
31727   zoom.translateExtent = function(_) {
31728     return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]];
31729   };
31730
31731   zoom.duration = function(_) {
31732     return arguments.length ? (duration = +_, zoom) : duration;
31733   };
31734
31735   zoom.on = function() {
31736     var value = listeners.on.apply(listeners, arguments);
31737     return value === listeners ? zoom : value;
31738   };
31739
31740   return zoom;
31741 };
31742
31743 var constant$11 = function(x) {
31744   return function() {
31745     return x;
31746   };
31747 };
31748
31749 var BrushEvent = function(target, type, selection) {
31750   this.target = target;
31751   this.type = type;
31752   this.selection = selection;
31753 };
31754
31755 function nopropagation$2() {
31756   event.stopImmediatePropagation();
31757 }
31758
31759 var noevent$2 = function() {
31760   event.preventDefault();
31761   event.stopImmediatePropagation();
31762 };
31763
31764 var MODE_DRAG = {name: "drag"};
31765 var MODE_SPACE = {name: "space"};
31766 var MODE_HANDLE = {name: "handle"};
31767 var MODE_CENTER = {name: "center"};
31768
31769 var X = {
31770   name: "x",
31771   handles: ["e", "w"].map(type$3),
31772   input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
31773   output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
31774 };
31775
31776 var Y = {
31777   name: "y",
31778   handles: ["n", "s"].map(type$3),
31779   input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
31780   output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
31781 };
31782
31783 var XY = {
31784   name: "xy",
31785   handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$3),
31786   input: function(xy) { return xy; },
31787   output: function(xy) { return xy; }
31788 };
31789
31790 var cursors = {
31791   overlay: "crosshair",
31792   selection: "move",
31793   n: "ns-resize",
31794   e: "ew-resize",
31795   s: "ns-resize",
31796   w: "ew-resize",
31797   nw: "nwse-resize",
31798   ne: "nesw-resize",
31799   se: "nwse-resize",
31800   sw: "nesw-resize"
31801 };
31802
31803 var flipX = {
31804   e: "w",
31805   w: "e",
31806   nw: "ne",
31807   ne: "nw",
31808   se: "sw",
31809   sw: "se"
31810 };
31811
31812 var flipY = {
31813   n: "s",
31814   s: "n",
31815   nw: "sw",
31816   ne: "se",
31817   se: "ne",
31818   sw: "nw"
31819 };
31820
31821 var signsX = {
31822   overlay: +1,
31823   selection: +1,
31824   n: null,
31825   e: +1,
31826   s: null,
31827   w: -1,
31828   nw: -1,
31829   ne: +1,
31830   se: +1,
31831   sw: -1
31832 };
31833
31834 var signsY = {
31835   overlay: +1,
31836   selection: +1,
31837   n: -1,
31838   e: null,
31839   s: +1,
31840   w: null,
31841   nw: -1,
31842   ne: -1,
31843   se: +1,
31844   sw: +1
31845 };
31846
31847 function type$3(t) {
31848   return {type: t};
31849 }
31850
31851 // Ignore right-click, since that should open the context menu.
31852 function defaultFilter$2() {
31853   return !event.button;
31854 }
31855
31856 function defaultExtent$1() {
31857   var svg = this.ownerSVGElement || this;
31858   return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
31859 }
31860
31861 // Like d3.local, but with the name “__brush” rather than auto-generated.
31862 function local$1(node) {
31863   while (!node.__brush) if (!(node = node.parentNode)) return;
31864   return node.__brush;
31865 }
31866
31867 function empty$1(extent) {
31868   return extent[0][0] === extent[1][0]
31869       || extent[0][1] === extent[1][1];
31870 }
31871
31872 function brushSelection(node) {
31873   var state = node.__brush;
31874   return state ? state.dim.output(state.selection) : null;
31875 }
31876
31877 function brushX() {
31878   return brush$1(X);
31879 }
31880
31881 function brushY() {
31882   return brush$1(Y);
31883 }
31884
31885 var brush = function() {
31886   return brush$1(XY);
31887 };
31888
31889 function brush$1(dim) {
31890   var extent = defaultExtent$1,
31891       filter = defaultFilter$2,
31892       listeners = dispatch(brush, "start", "brush", "end"),
31893       handleSize = 6,
31894       touchending;
31895
31896   function brush(group) {
31897     var overlay = group
31898         .property("__brush", initialize)
31899       .selectAll(".overlay")
31900       .data([type$3("overlay")]);
31901
31902     overlay.enter().append("rect")
31903         .attr("class", "overlay")
31904         .attr("pointer-events", "all")
31905         .attr("cursor", cursors.overlay)
31906       .merge(overlay)
31907         .each(function() {
31908           var extent = local$1(this).extent;
31909           select(this)
31910               .attr("x", extent[0][0])
31911               .attr("y", extent[0][1])
31912               .attr("width", extent[1][0] - extent[0][0])
31913               .attr("height", extent[1][1] - extent[0][1]);
31914         });
31915
31916     group.selectAll(".selection")
31917       .data([type$3("selection")])
31918       .enter().append("rect")
31919         .attr("class", "selection")
31920         .attr("cursor", cursors.selection)
31921         .attr("fill", "#777")
31922         .attr("fill-opacity", 0.3)
31923         .attr("stroke", "#fff")
31924         .attr("shape-rendering", "crispEdges");
31925
31926     var handle = group.selectAll(".handle")
31927       .data(dim.handles, function(d) { return d.type; });
31928
31929     handle.exit().remove();
31930
31931     handle.enter().append("rect")
31932         .attr("class", function(d) { return "handle handle--" + d.type; })
31933         .attr("cursor", function(d) { return cursors[d.type]; });
31934
31935     group
31936         .each(redraw)
31937         .attr("fill", "none")
31938         .attr("pointer-events", "all")
31939         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
31940         .on("mousedown.brush touchstart.brush", started);
31941   }
31942
31943   brush.move = function(group, selection$$1) {
31944     if (group.selection) {
31945       group
31946           .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
31947           .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
31948           .tween("brush", function() {
31949             var that = this,
31950                 state = that.__brush,
31951                 emit = emitter(that, arguments),
31952                 selection0 = state.selection,
31953                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent),
31954                 i = interpolate(selection0, selection1);
31955
31956             function tween(t) {
31957               state.selection = t === 1 && empty$1(selection1) ? null : i(t);
31958               redraw.call(that);
31959               emit.brush();
31960             }
31961
31962             return selection0 && selection1 ? tween : tween(1);
31963           });
31964     } else {
31965       group
31966           .each(function() {
31967             var that = this,
31968                 args = arguments,
31969                 state = that.__brush,
31970                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent),
31971                 emit = emitter(that, args).beforestart();
31972
31973             interrupt(that);
31974             state.selection = selection1 == null || empty$1(selection1) ? null : selection1;
31975             redraw.call(that);
31976             emit.start().brush().end();
31977           });
31978     }
31979   };
31980
31981   function redraw() {
31982     var group = select(this),
31983         selection$$1 = local$1(this).selection;
31984
31985     if (selection$$1) {
31986       group.selectAll(".selection")
31987           .style("display", null)
31988           .attr("x", selection$$1[0][0])
31989           .attr("y", selection$$1[0][1])
31990           .attr("width", selection$$1[1][0] - selection$$1[0][0])
31991           .attr("height", selection$$1[1][1] - selection$$1[0][1]);
31992
31993       group.selectAll(".handle")
31994           .style("display", null)
31995           .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; })
31996           .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; })
31997           .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; })
31998           .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; });
31999     }
32000
32001     else {
32002       group.selectAll(".selection,.handle")
32003           .style("display", "none")
32004           .attr("x", null)
32005           .attr("y", null)
32006           .attr("width", null)
32007           .attr("height", null);
32008     }
32009   }
32010
32011   function emitter(that, args) {
32012     return that.__brush.emitter || new Emitter(that, args);
32013   }
32014
32015   function Emitter(that, args) {
32016     this.that = that;
32017     this.args = args;
32018     this.state = that.__brush;
32019     this.active = 0;
32020   }
32021
32022   Emitter.prototype = {
32023     beforestart: function() {
32024       if (++this.active === 1) this.state.emitter = this, this.starting = true;
32025       return this;
32026     },
32027     start: function() {
32028       if (this.starting) this.starting = false, this.emit("start");
32029       return this;
32030     },
32031     brush: function() {
32032       this.emit("brush");
32033       return this;
32034     },
32035     end: function() {
32036       if (--this.active === 0) delete this.state.emitter, this.emit("end");
32037       return this;
32038     },
32039     emit: function(type) {
32040       customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
32041     }
32042   };
32043
32044   function started() {
32045     if (event.touches) { if (event.changedTouches.length < event.touches.length) return noevent$2(); }
32046     else if (touchending) return;
32047     if (!filter.apply(this, arguments)) return;
32048
32049     var that = this,
32050         type = event.target.__data__.type,
32051         mode = (event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (event.altKey ? MODE_CENTER : MODE_HANDLE),
32052         signX = dim === Y ? null : signsX[type],
32053         signY = dim === X ? null : signsY[type],
32054         state = local$1(that),
32055         extent = state.extent,
32056         selection$$1 = state.selection,
32057         W = extent[0][0], w0, w1,
32058         N = extent[0][1], n0, n1,
32059         E = extent[1][0], e0, e1,
32060         S = extent[1][1], s0, s1,
32061         dx,
32062         dy,
32063         moving,
32064         shifting = signX && signY && event.shiftKey,
32065         lockX,
32066         lockY,
32067         point0 = mouse(that),
32068         point = point0,
32069         emit = emitter(that, arguments).beforestart();
32070
32071     if (type === "overlay") {
32072       state.selection = selection$$1 = [
32073         [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
32074         [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
32075       ];
32076     } else {
32077       w0 = selection$$1[0][0];
32078       n0 = selection$$1[0][1];
32079       e0 = selection$$1[1][0];
32080       s0 = selection$$1[1][1];
32081     }
32082
32083     w1 = w0;
32084     n1 = n0;
32085     e1 = e0;
32086     s1 = s0;
32087
32088     var group = select(that)
32089         .attr("pointer-events", "none");
32090
32091     var overlay = group.selectAll(".overlay")
32092         .attr("cursor", cursors[type]);
32093
32094     if (event.touches) {
32095       group
32096           .on("touchmove.brush", moved, true)
32097           .on("touchend.brush touchcancel.brush", ended, true);
32098     } else {
32099       var view = select(event.view)
32100           .on("keydown.brush", keydowned, true)
32101           .on("keyup.brush", keyupped, true)
32102           .on("mousemove.brush", moved, true)
32103           .on("mouseup.brush", ended, true);
32104
32105       dragDisable(event.view);
32106     }
32107
32108     nopropagation$2();
32109     interrupt(that);
32110     redraw.call(that);
32111     emit.start();
32112
32113     function moved() {
32114       var point1 = mouse(that);
32115       if (shifting && !lockX && !lockY) {
32116         if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
32117         else lockX = true;
32118       }
32119       point = point1;
32120       moving = true;
32121       noevent$2();
32122       move();
32123     }
32124
32125     function move() {
32126       var t;
32127
32128       dx = point[0] - point0[0];
32129       dy = point[1] - point0[1];
32130
32131       switch (mode) {
32132         case MODE_SPACE:
32133         case MODE_DRAG: {
32134           if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
32135           if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
32136           break;
32137         }
32138         case MODE_HANDLE: {
32139           if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
32140           else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
32141           if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
32142           else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
32143           break;
32144         }
32145         case MODE_CENTER: {
32146           if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
32147           if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
32148           break;
32149         }
32150       }
32151
32152       if (e1 < w1) {
32153         signX *= -1;
32154         t = w0, w0 = e0, e0 = t;
32155         t = w1, w1 = e1, e1 = t;
32156         if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
32157       }
32158
32159       if (s1 < n1) {
32160         signY *= -1;
32161         t = n0, n0 = s0, s0 = t;
32162         t = n1, n1 = s1, s1 = t;
32163         if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
32164       }
32165
32166       if (state.selection) selection$$1 = state.selection; // May be set by brush.move!
32167       if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0];
32168       if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1];
32169
32170       if (selection$$1[0][0] !== w1
32171           || selection$$1[0][1] !== n1
32172           || selection$$1[1][0] !== e1
32173           || selection$$1[1][1] !== s1) {
32174         state.selection = [[w1, n1], [e1, s1]];
32175         redraw.call(that);
32176         emit.brush();
32177       }
32178     }
32179
32180     function ended() {
32181       nopropagation$2();
32182       if (event.touches) {
32183         if (event.touches.length) return;
32184         if (touchending) clearTimeout(touchending);
32185         touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
32186         group.on("touchmove.brush touchend.brush touchcancel.brush", null);
32187       } else {
32188         yesdrag(event.view, moving);
32189         view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
32190       }
32191       group.attr("pointer-events", "all");
32192       overlay.attr("cursor", cursors.overlay);
32193       if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)!
32194       if (empty$1(selection$$1)) state.selection = null, redraw.call(that);
32195       emit.end();
32196     }
32197
32198     function keydowned() {
32199       switch (event.keyCode) {
32200         case 16: { // SHIFT
32201           shifting = signX && signY;
32202           break;
32203         }
32204         case 18: { // ALT
32205           if (mode === MODE_HANDLE) {
32206             if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
32207             if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
32208             mode = MODE_CENTER;
32209             move();
32210           }
32211           break;
32212         }
32213         case 32: { // SPACE; takes priority over ALT
32214           if (mode === MODE_HANDLE || mode === MODE_CENTER) {
32215             if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
32216             if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
32217             mode = MODE_SPACE;
32218             overlay.attr("cursor", cursors.selection);
32219             move();
32220           }
32221           break;
32222         }
32223         default: return;
32224       }
32225       noevent$2();
32226     }
32227
32228     function keyupped() {
32229       switch (event.keyCode) {
32230         case 16: { // SHIFT
32231           if (shifting) {
32232             lockX = lockY = shifting = false;
32233             move();
32234           }
32235           break;
32236         }
32237         case 18: { // ALT
32238           if (mode === MODE_CENTER) {
32239             if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
32240             if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
32241             mode = MODE_HANDLE;
32242             move();
32243           }
32244           break;
32245         }
32246         case 32: { // SPACE
32247           if (mode === MODE_SPACE) {
32248             if (event.altKey) {
32249               if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
32250               if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
32251               mode = MODE_CENTER;
32252             } else {
32253               if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
32254               if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
32255               mode = MODE_HANDLE;
32256             }
32257             overlay.attr("cursor", cursors[type]);
32258             move();
32259           }
32260           break;
32261         }
32262         default: return;
32263       }
32264       noevent$2();
32265     }
32266   }
32267
32268   function initialize() {
32269     var state = this.__brush || {selection: null};
32270     state.extent = extent.apply(this, arguments);
32271     state.dim = dim;
32272     return state;
32273   }
32274
32275   brush.extent = function(_) {
32276     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$11([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
32277   };
32278
32279   brush.filter = function(_) {
32280     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$11(!!_), brush) : filter;
32281   };
32282
32283   brush.handleSize = function(_) {
32284     return arguments.length ? (handleSize = +_, brush) : handleSize;
32285   };
32286
32287   brush.on = function() {
32288     var value = listeners.on.apply(listeners, arguments);
32289     return value === listeners ? brush : value;
32290   };
32291
32292   return brush;
32293 }
32294
32295 var cos = Math.cos;
32296 var sin = Math.sin;
32297 var pi$3 = Math.PI;
32298 var halfPi$2 = pi$3 / 2;
32299 var tau$3 = pi$3 * 2;
32300 var max$1 = Math.max;
32301
32302 function compareValue(compare) {
32303   return function(a, b) {
32304     return compare(
32305       a.source.value + a.target.value,
32306       b.source.value + b.target.value
32307     );
32308   };
32309 }
32310
32311 var chord = function() {
32312   var padAngle = 0,
32313       sortGroups = null,
32314       sortSubgroups = null,
32315       sortChords = null;
32316
32317   function chord(matrix) {
32318     var n = matrix.length,
32319         groupSums = [],
32320         groupIndex = range(n),
32321         subgroupIndex = [],
32322         chords = [],
32323         groups = chords.groups = new Array(n),
32324         subgroups = new Array(n * n),
32325         k,
32326         x,
32327         x0,
32328         dx,
32329         i,
32330         j;
32331
32332     // Compute the sum.
32333     k = 0, i = -1; while (++i < n) {
32334       x = 0, j = -1; while (++j < n) {
32335         x += matrix[i][j];
32336       }
32337       groupSums.push(x);
32338       subgroupIndex.push(range(n));
32339       k += x;
32340     }
32341
32342     // Sort groups…
32343     if (sortGroups) groupIndex.sort(function(a, b) {
32344       return sortGroups(groupSums[a], groupSums[b]);
32345     });
32346
32347     // Sort subgroups…
32348     if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
32349       d.sort(function(a, b) {
32350         return sortSubgroups(matrix[i][a], matrix[i][b]);
32351       });
32352     });
32353
32354     // Convert the sum to scaling factor for [0, 2pi].
32355     // TODO Allow start and end angle to be specified?
32356     // TODO Allow padding to be specified as percentage?
32357     k = max$1(0, tau$3 - padAngle * n) / k;
32358     dx = k ? padAngle : tau$3 / n;
32359
32360     // Compute the start and end angle for each group and subgroup.
32361     // Note: Opera has a bug reordering object literal properties!
32362     x = 0, i = -1; while (++i < n) {
32363       x0 = x, j = -1; while (++j < n) {
32364         var di = groupIndex[i],
32365             dj = subgroupIndex[di][j],
32366             v = matrix[di][dj],
32367             a0 = x,
32368             a1 = x += v * k;
32369         subgroups[dj * n + di] = {
32370           index: di,
32371           subindex: dj,
32372           startAngle: a0,
32373           endAngle: a1,
32374           value: v
32375         };
32376       }
32377       groups[di] = {
32378         index: di,
32379         startAngle: x0,
32380         endAngle: x,
32381         value: groupSums[di]
32382       };
32383       x += dx;
32384     }
32385
32386     // Generate chords for each (non-empty) subgroup-subgroup link.
32387     i = -1; while (++i < n) {
32388       j = i - 1; while (++j < n) {
32389         var source = subgroups[j * n + i],
32390             target = subgroups[i * n + j];
32391         if (source.value || target.value) {
32392           chords.push(source.value < target.value
32393               ? {source: target, target: source}
32394               : {source: source, target: target});
32395         }
32396       }
32397     }
32398
32399     return sortChords ? chords.sort(sortChords) : chords;
32400   }
32401
32402   chord.padAngle = function(_) {
32403     return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle;
32404   };
32405
32406   chord.sortGroups = function(_) {
32407     return arguments.length ? (sortGroups = _, chord) : sortGroups;
32408   };
32409
32410   chord.sortSubgroups = function(_) {
32411     return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
32412   };
32413
32414   chord.sortChords = function(_) {
32415     return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
32416   };
32417
32418   return chord;
32419 };
32420
32421 var slice$5 = Array.prototype.slice;
32422
32423 var constant$12 = function(x) {
32424   return function() {
32425     return x;
32426   };
32427 };
32428
32429 function defaultSource(d) {
32430   return d.source;
32431 }
32432
32433 function defaultTarget(d) {
32434   return d.target;
32435 }
32436
32437 function defaultRadius$1(d) {
32438   return d.radius;
32439 }
32440
32441 function defaultStartAngle(d) {
32442   return d.startAngle;
32443 }
32444
32445 function defaultEndAngle(d) {
32446   return d.endAngle;
32447 }
32448
32449 var ribbon = function() {
32450   var source = defaultSource,
32451       target = defaultTarget,
32452       radius = defaultRadius$1,
32453       startAngle = defaultStartAngle,
32454       endAngle = defaultEndAngle,
32455       context = null;
32456
32457   function ribbon() {
32458     var buffer,
32459         argv = slice$5.call(arguments),
32460         s = source.apply(this, argv),
32461         t = target.apply(this, argv),
32462         sr = +radius.apply(this, (argv[0] = s, argv)),
32463         sa0 = startAngle.apply(this, argv) - halfPi$2,
32464         sa1 = endAngle.apply(this, argv) - halfPi$2,
32465         sx0 = sr * cos(sa0),
32466         sy0 = sr * sin(sa0),
32467         tr = +radius.apply(this, (argv[0] = t, argv)),
32468         ta0 = startAngle.apply(this, argv) - halfPi$2,
32469         ta1 = endAngle.apply(this, argv) - halfPi$2;
32470
32471     if (!context) context = buffer = path();
32472
32473     context.moveTo(sx0, sy0);
32474     context.arc(0, 0, sr, sa0, sa1);
32475     if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
32476       context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
32477       context.arc(0, 0, tr, ta0, ta1);
32478     }
32479     context.quadraticCurveTo(0, 0, sx0, sy0);
32480     context.closePath();
32481
32482     if (buffer) return context = null, buffer + "" || null;
32483   }
32484
32485   ribbon.radius = function(_) {
32486     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$12(+_), ribbon) : radius;
32487   };
32488
32489   ribbon.startAngle = function(_) {
32490     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : startAngle;
32491   };
32492
32493   ribbon.endAngle = function(_) {
32494     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : endAngle;
32495   };
32496
32497   ribbon.source = function(_) {
32498     return arguments.length ? (source = _, ribbon) : source;
32499   };
32500
32501   ribbon.target = function(_) {
32502     return arguments.length ? (target = _, ribbon) : target;
32503   };
32504
32505   ribbon.context = function(_) {
32506     return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
32507   };
32508
32509   return ribbon;
32510 };
32511
32512 // Adds floating point numbers with twice the normal precision.
32513 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
32514 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
32515 // 305–363 (1997).
32516 // Code adapted from GeographicLib by Charles F. F. Karney,
32517 // http://geographiclib.sourceforge.net/
32518
32519 var adder = function() {
32520   return new Adder;
32521 };
32522
32523 function Adder() {
32524   this.reset();
32525 }
32526
32527 Adder.prototype = {
32528   constructor: Adder,
32529   reset: function() {
32530     this.s = // rounded value
32531     this.t = 0; // exact error
32532   },
32533   add: function(y) {
32534     add$1(temp, y, this.t);
32535     add$1(this, temp.s, this.s);
32536     if (this.s) this.t += temp.t;
32537     else this.s = temp.t;
32538   },
32539   valueOf: function() {
32540     return this.s;
32541   }
32542 };
32543
32544 var temp = new Adder;
32545
32546 function add$1(adder, a, b) {
32547   var x = adder.s = a + b,
32548       bv = x - a,
32549       av = x - bv;
32550   adder.t = (a - av) + (b - bv);
32551 }
32552
32553 var epsilon$4 = 1e-6;
32554 var epsilon2$2 = 1e-12;
32555 var pi$4 = Math.PI;
32556 var halfPi$3 = pi$4 / 2;
32557 var quarterPi = pi$4 / 4;
32558 var tau$4 = pi$4 * 2;
32559
32560 var degrees$1 = 180 / pi$4;
32561 var radians = pi$4 / 180;
32562
32563 var abs = Math.abs;
32564 var atan = Math.atan;
32565 var atan2 = Math.atan2;
32566 var cos$1 = Math.cos;
32567 var ceil = Math.ceil;
32568 var exp = Math.exp;
32569
32570 var log$1 = Math.log;
32571 var pow$1 = Math.pow;
32572 var sin$1 = Math.sin;
32573 var sign$1 = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
32574 var sqrt$1 = Math.sqrt;
32575 var tan = Math.tan;
32576
32577 function acos(x) {
32578   return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x);
32579 }
32580
32581 function asin$1(x) {
32582   return x > 1 ? halfPi$3 : x < -1 ? -halfPi$3 : Math.asin(x);
32583 }
32584
32585 function haversin(x) {
32586   return (x = sin$1(x / 2)) * x;
32587 }
32588
32589 function noop$2() {}
32590
32591 function streamGeometry(geometry, stream) {
32592   if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
32593     streamGeometryType[geometry.type](geometry, stream);
32594   }
32595 }
32596
32597 var streamObjectType = {
32598   Feature: function(feature, stream) {
32599     streamGeometry(feature.geometry, stream);
32600   },
32601   FeatureCollection: function(object, stream) {
32602     var features = object.features, i = -1, n = features.length;
32603     while (++i < n) streamGeometry(features[i].geometry, stream);
32604   }
32605 };
32606
32607 var streamGeometryType = {
32608   Sphere: function(object, stream) {
32609     stream.sphere();
32610   },
32611   Point: function(object, stream) {
32612     object = object.coordinates;
32613     stream.point(object[0], object[1], object[2]);
32614   },
32615   MultiPoint: function(object, stream) {
32616     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32617     while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
32618   },
32619   LineString: function(object, stream) {
32620     streamLine(object.coordinates, stream, 0);
32621   },
32622   MultiLineString: function(object, stream) {
32623     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32624     while (++i < n) streamLine(coordinates[i], stream, 0);
32625   },
32626   Polygon: function(object, stream) {
32627     streamPolygon(object.coordinates, stream);
32628   },
32629   MultiPolygon: function(object, stream) {
32630     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32631     while (++i < n) streamPolygon(coordinates[i], stream);
32632   },
32633   GeometryCollection: function(object, stream) {
32634     var geometries = object.geometries, i = -1, n = geometries.length;
32635     while (++i < n) streamGeometry(geometries[i], stream);
32636   }
32637 };
32638
32639 function streamLine(coordinates, stream, closed) {
32640   var i = -1, n = coordinates.length - closed, coordinate;
32641   stream.lineStart();
32642   while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
32643   stream.lineEnd();
32644 }
32645
32646 function streamPolygon(coordinates, stream) {
32647   var i = -1, n = coordinates.length;
32648   stream.polygonStart();
32649   while (++i < n) streamLine(coordinates[i], stream, 1);
32650   stream.polygonEnd();
32651 }
32652
32653 var geoStream = function(object, stream) {
32654   if (object && streamObjectType.hasOwnProperty(object.type)) {
32655     streamObjectType[object.type](object, stream);
32656   } else {
32657     streamGeometry(object, stream);
32658   }
32659 };
32660
32661 var areaRingSum = adder();
32662
32663 var areaSum = adder();
32664 var lambda00;
32665 var phi00;
32666 var lambda0;
32667 var cosPhi0;
32668 var sinPhi0;
32669
32670 var areaStream = {
32671   point: noop$2,
32672   lineStart: noop$2,
32673   lineEnd: noop$2,
32674   polygonStart: function() {
32675     areaRingSum.reset();
32676     areaStream.lineStart = areaRingStart;
32677     areaStream.lineEnd = areaRingEnd;
32678   },
32679   polygonEnd: function() {
32680     var areaRing = +areaRingSum;
32681     areaSum.add(areaRing < 0 ? tau$4 + areaRing : areaRing);
32682     this.lineStart = this.lineEnd = this.point = noop$2;
32683   },
32684   sphere: function() {
32685     areaSum.add(tau$4);
32686   }
32687 };
32688
32689 function areaRingStart() {
32690   areaStream.point = areaPointFirst;
32691 }
32692
32693 function areaRingEnd() {
32694   areaPoint(lambda00, phi00);
32695 }
32696
32697 function areaPointFirst(lambda, phi) {
32698   areaStream.point = areaPoint;
32699   lambda00 = lambda, phi00 = phi;
32700   lambda *= radians, phi *= radians;
32701   lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi);
32702 }
32703
32704 function areaPoint(lambda, phi) {
32705   lambda *= radians, phi *= radians;
32706   phi = phi / 2 + quarterPi; // half the angular distance from south pole
32707
32708   // Spherical excess E for a spherical triangle with vertices: south pole,
32709   // previous point, current point.  Uses a formula derived from Cagnoli’s
32710   // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
32711   var dLambda = lambda - lambda0,
32712       sdLambda = dLambda >= 0 ? 1 : -1,
32713       adLambda = sdLambda * dLambda,
32714       cosPhi = cos$1(phi),
32715       sinPhi = sin$1(phi),
32716       k = sinPhi0 * sinPhi,
32717       u = cosPhi0 * cosPhi + k * cos$1(adLambda),
32718       v = k * sdLambda * sin$1(adLambda);
32719   areaRingSum.add(atan2(v, u));
32720
32721   // Advance the previous points.
32722   lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
32723 }
32724
32725 var area$1 = function(object) {
32726   areaSum.reset();
32727   geoStream(object, areaStream);
32728   return areaSum * 2;
32729 };
32730
32731 function spherical(cartesian) {
32732   return [atan2(cartesian[1], cartesian[0]), asin$1(cartesian[2])];
32733 }
32734
32735 function cartesian(spherical) {
32736   var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi);
32737   return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)];
32738 }
32739
32740 function cartesianDot(a, b) {
32741   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
32742 }
32743
32744 function cartesianCross(a, b) {
32745   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]];
32746 }
32747
32748 // TODO return a
32749 function cartesianAddInPlace(a, b) {
32750   a[0] += b[0], a[1] += b[1], a[2] += b[2];
32751 }
32752
32753 function cartesianScale(vector, k) {
32754   return [vector[0] * k, vector[1] * k, vector[2] * k];
32755 }
32756
32757 // TODO return d
32758 function cartesianNormalizeInPlace(d) {
32759   var l = sqrt$1(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
32760   d[0] /= l, d[1] /= l, d[2] /= l;
32761 }
32762
32763 var lambda0$1;
32764 var phi0;
32765 var lambda1;
32766 var phi1;
32767 var lambda2;
32768 var lambda00$1;
32769 var phi00$1;
32770 var p0;
32771 var deltaSum = adder();
32772 var ranges;
32773 var range$1;
32774
32775 var boundsStream = {
32776   point: boundsPoint,
32777   lineStart: boundsLineStart,
32778   lineEnd: boundsLineEnd,
32779   polygonStart: function() {
32780     boundsStream.point = boundsRingPoint;
32781     boundsStream.lineStart = boundsRingStart;
32782     boundsStream.lineEnd = boundsRingEnd;
32783     deltaSum.reset();
32784     areaStream.polygonStart();
32785   },
32786   polygonEnd: function() {
32787     areaStream.polygonEnd();
32788     boundsStream.point = boundsPoint;
32789     boundsStream.lineStart = boundsLineStart;
32790     boundsStream.lineEnd = boundsLineEnd;
32791     if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
32792     else if (deltaSum > epsilon$4) phi1 = 90;
32793     else if (deltaSum < -epsilon$4) phi0 = -90;
32794     range$1[0] = lambda0$1, range$1[1] = lambda1;
32795   }
32796 };
32797
32798 function boundsPoint(lambda, phi) {
32799   ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]);
32800   if (phi < phi0) phi0 = phi;
32801   if (phi > phi1) phi1 = phi;
32802 }
32803
32804 function linePoint(lambda, phi) {
32805   var p = cartesian([lambda * radians, phi * radians]);
32806   if (p0) {
32807     var normal = cartesianCross(p0, p),
32808         equatorial = [normal[1], -normal[0], 0],
32809         inflection = cartesianCross(equatorial, normal);
32810     cartesianNormalizeInPlace(inflection);
32811     inflection = spherical(inflection);
32812     var delta = lambda - lambda2,
32813         sign$$1 = delta > 0 ? 1 : -1,
32814         lambdai = inflection[0] * degrees$1 * sign$$1,
32815         phii,
32816         antimeridian = abs(delta) > 180;
32817     if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
32818       phii = inflection[1] * degrees$1;
32819       if (phii > phi1) phi1 = phii;
32820     } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
32821       phii = -inflection[1] * degrees$1;
32822       if (phii < phi0) phi0 = phii;
32823     } else {
32824       if (phi < phi0) phi0 = phi;
32825       if (phi > phi1) phi1 = phi;
32826     }
32827     if (antimeridian) {
32828       if (lambda < lambda2) {
32829         if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
32830       } else {
32831         if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
32832       }
32833     } else {
32834       if (lambda1 >= lambda0$1) {
32835         if (lambda < lambda0$1) lambda0$1 = lambda;
32836         if (lambda > lambda1) lambda1 = lambda;
32837       } else {
32838         if (lambda > lambda2) {
32839           if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
32840         } else {
32841           if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
32842         }
32843       }
32844     }
32845   } else {
32846     boundsPoint(lambda, phi);
32847   }
32848   p0 = p, lambda2 = lambda;
32849 }
32850
32851 function boundsLineStart() {
32852   boundsStream.point = linePoint;
32853 }
32854
32855 function boundsLineEnd() {
32856   range$1[0] = lambda0$1, range$1[1] = lambda1;
32857   boundsStream.point = boundsPoint;
32858   p0 = null;
32859 }
32860
32861 function boundsRingPoint(lambda, phi) {
32862   if (p0) {
32863     var delta = lambda - lambda2;
32864     deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
32865   } else {
32866     lambda00$1 = lambda, phi00$1 = phi;
32867   }
32868   areaStream.point(lambda, phi);
32869   linePoint(lambda, phi);
32870 }
32871
32872 function boundsRingStart() {
32873   areaStream.lineStart();
32874 }
32875
32876 function boundsRingEnd() {
32877   boundsRingPoint(lambda00$1, phi00$1);
32878   areaStream.lineEnd();
32879   if (abs(deltaSum) > epsilon$4) lambda0$1 = -(lambda1 = 180);
32880   range$1[0] = lambda0$1, range$1[1] = lambda1;
32881   p0 = null;
32882 }
32883
32884 // Finds the left-right distance between two longitudes.
32885 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
32886 // the distance between ±180° to be 360°.
32887 function angle(lambda0, lambda1) {
32888   return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
32889 }
32890
32891 function rangeCompare(a, b) {
32892   return a[0] - b[0];
32893 }
32894
32895 function rangeContains(range, x) {
32896   return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
32897 }
32898
32899 var bounds = function(feature) {
32900   var i, n, a, b, merged, deltaMax, delta;
32901
32902   phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
32903   ranges = [];
32904   geoStream(feature, boundsStream);
32905
32906   // First, sort ranges by their minimum longitudes.
32907   if (n = ranges.length) {
32908     ranges.sort(rangeCompare);
32909
32910     // Then, merge any ranges that overlap.
32911     for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
32912       b = ranges[i];
32913       if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
32914         if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
32915         if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
32916       } else {
32917         merged.push(a = b);
32918       }
32919     }
32920
32921     // Finally, find the largest gap between the merged ranges.
32922     // The final bounding box will be the inverse of this gap.
32923     for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
32924       b = merged[i];
32925       if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
32926     }
32927   }
32928
32929   ranges = range$1 = null;
32930
32931   return lambda0$1 === Infinity || phi0 === Infinity
32932       ? [[NaN, NaN], [NaN, NaN]]
32933       : [[lambda0$1, phi0], [lambda1, phi1]];
32934 };
32935
32936 var W0;
32937 var W1;
32938 var X0;
32939 var Y0;
32940 var Z0;
32941 var X1;
32942 var Y1;
32943 var Z1;
32944 var X2;
32945 var Y2;
32946 var Z2;
32947 var lambda00$2;
32948 var phi00$2;
32949 var x0;
32950 var y0;
32951 var z0; // previous point
32952
32953 var centroidStream = {
32954   sphere: noop$2,
32955   point: centroidPoint,
32956   lineStart: centroidLineStart,
32957   lineEnd: centroidLineEnd,
32958   polygonStart: function() {
32959     centroidStream.lineStart = centroidRingStart;
32960     centroidStream.lineEnd = centroidRingEnd;
32961   },
32962   polygonEnd: function() {
32963     centroidStream.lineStart = centroidLineStart;
32964     centroidStream.lineEnd = centroidLineEnd;
32965   }
32966 };
32967
32968 // Arithmetic mean of Cartesian vectors.
32969 function centroidPoint(lambda, phi) {
32970   lambda *= radians, phi *= radians;
32971   var cosPhi = cos$1(phi);
32972   centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi));
32973 }
32974
32975 function centroidPointCartesian(x, y, z) {
32976   ++W0;
32977   X0 += (x - X0) / W0;
32978   Y0 += (y - Y0) / W0;
32979   Z0 += (z - Z0) / W0;
32980 }
32981
32982 function centroidLineStart() {
32983   centroidStream.point = centroidLinePointFirst;
32984 }
32985
32986 function centroidLinePointFirst(lambda, phi) {
32987   lambda *= radians, phi *= radians;
32988   var cosPhi = cos$1(phi);
32989   x0 = cosPhi * cos$1(lambda);
32990   y0 = cosPhi * sin$1(lambda);
32991   z0 = sin$1(phi);
32992   centroidStream.point = centroidLinePoint;
32993   centroidPointCartesian(x0, y0, z0);
32994 }
32995
32996 function centroidLinePoint(lambda, phi) {
32997   lambda *= radians, phi *= radians;
32998   var cosPhi = cos$1(phi),
32999       x = cosPhi * cos$1(lambda),
33000       y = cosPhi * sin$1(lambda),
33001       z = sin$1(phi),
33002       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);
33003   W1 += w;
33004   X1 += w * (x0 + (x0 = x));
33005   Y1 += w * (y0 + (y0 = y));
33006   Z1 += w * (z0 + (z0 = z));
33007   centroidPointCartesian(x0, y0, z0);
33008 }
33009
33010 function centroidLineEnd() {
33011   centroidStream.point = centroidPoint;
33012 }
33013
33014 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
33015 // J. Applied Mechanics 42, 239 (1975).
33016 function centroidRingStart() {
33017   centroidStream.point = centroidRingPointFirst;
33018 }
33019
33020 function centroidRingEnd() {
33021   centroidRingPoint(lambda00$2, phi00$2);
33022   centroidStream.point = centroidPoint;
33023 }
33024
33025 function centroidRingPointFirst(lambda, phi) {
33026   lambda00$2 = lambda, phi00$2 = phi;
33027   lambda *= radians, phi *= radians;
33028   centroidStream.point = centroidRingPoint;
33029   var cosPhi = cos$1(phi);
33030   x0 = cosPhi * cos$1(lambda);
33031   y0 = cosPhi * sin$1(lambda);
33032   z0 = sin$1(phi);
33033   centroidPointCartesian(x0, y0, z0);
33034 }
33035
33036 function centroidRingPoint(lambda, phi) {
33037   lambda *= radians, phi *= radians;
33038   var cosPhi = cos$1(phi),
33039       x = cosPhi * cos$1(lambda),
33040       y = cosPhi * sin$1(lambda),
33041       z = sin$1(phi),
33042       cx = y0 * z - z0 * y,
33043       cy = z0 * x - x0 * z,
33044       cz = x0 * y - y0 * x,
33045       m = sqrt$1(cx * cx + cy * cy + cz * cz),
33046       u = x0 * x + y0 * y + z0 * z,
33047       v = m && -acos(u) / m, // area weight
33048       w = atan2(m, u); // line weight
33049   X2 += v * cx;
33050   Y2 += v * cy;
33051   Z2 += v * cz;
33052   W1 += w;
33053   X1 += w * (x0 + (x0 = x));
33054   Y1 += w * (y0 + (y0 = y));
33055   Z1 += w * (z0 + (z0 = z));
33056   centroidPointCartesian(x0, y0, z0);
33057 }
33058
33059 var d3GeoCentroid = function(object) {
33060   W0 = W1 =
33061   X0 = Y0 = Z0 =
33062   X1 = Y1 = Z1 =
33063   X2 = Y2 = Z2 = 0;
33064   geoStream(object, centroidStream);
33065
33066   var x = X2,
33067       y = Y2,
33068       z = Z2,
33069       m = x * x + y * y + z * z;
33070
33071   // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
33072   if (m < epsilon2$2) {
33073     x = X1, y = Y1, z = Z1;
33074     // If the feature has zero length, fall back to arithmetic mean of point vectors.
33075     if (W1 < epsilon$4) x = X0, y = Y0, z = Z0;
33076     m = x * x + y * y + z * z;
33077     // If the feature still has an undefined ccentroid, then return.
33078     if (m < epsilon2$2) return [NaN, NaN];
33079   }
33080
33081   return [atan2(y, x) * degrees$1, asin$1(z / sqrt$1(m)) * degrees$1];
33082 };
33083
33084 var constant$13 = function(x) {
33085   return function() {
33086     return x;
33087   };
33088 };
33089
33090 var compose = function(a, b) {
33091
33092   function compose(x, y) {
33093     return x = a(x, y), b(x[0], x[1]);
33094   }
33095
33096   if (a.invert && b.invert) compose.invert = function(x, y) {
33097     return x = b.invert(x, y), x && a.invert(x[0], x[1]);
33098   };
33099
33100   return compose;
33101 };
33102
33103 function rotationIdentity(lambda, phi) {
33104   return [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi];
33105 }
33106
33107 rotationIdentity.invert = rotationIdentity;
33108
33109 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
33110   return (deltaLambda %= tau$4) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
33111     : rotationLambda(deltaLambda))
33112     : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
33113     : rotationIdentity);
33114 }
33115
33116 function forwardRotationLambda(deltaLambda) {
33117   return function(lambda, phi) {
33118     return lambda += deltaLambda, [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi];
33119   };
33120 }
33121
33122 function rotationLambda(deltaLambda) {
33123   var rotation = forwardRotationLambda(deltaLambda);
33124   rotation.invert = forwardRotationLambda(-deltaLambda);
33125   return rotation;
33126 }
33127
33128 function rotationPhiGamma(deltaPhi, deltaGamma) {
33129   var cosDeltaPhi = cos$1(deltaPhi),
33130       sinDeltaPhi = sin$1(deltaPhi),
33131       cosDeltaGamma = cos$1(deltaGamma),
33132       sinDeltaGamma = sin$1(deltaGamma);
33133
33134   function rotation(lambda, phi) {
33135     var cosPhi = cos$1(phi),
33136         x = cos$1(lambda) * cosPhi,
33137         y = sin$1(lambda) * cosPhi,
33138         z = sin$1(phi),
33139         k = z * cosDeltaPhi + x * sinDeltaPhi;
33140     return [
33141       atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
33142       asin$1(k * cosDeltaGamma + y * sinDeltaGamma)
33143     ];
33144   }
33145
33146   rotation.invert = function(lambda, phi) {
33147     var cosPhi = cos$1(phi),
33148         x = cos$1(lambda) * cosPhi,
33149         y = sin$1(lambda) * cosPhi,
33150         z = sin$1(phi),
33151         k = z * cosDeltaGamma - y * sinDeltaGamma;
33152     return [
33153       atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
33154       asin$1(k * cosDeltaPhi - x * sinDeltaPhi)
33155     ];
33156   };
33157
33158   return rotation;
33159 }
33160
33161 var rotation = function(rotate) {
33162   rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
33163
33164   function forward(coordinates) {
33165     coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
33166     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
33167   }
33168
33169   forward.invert = function(coordinates) {
33170     coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
33171     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
33172   };
33173
33174   return forward;
33175 };
33176
33177 // Generates a circle centered at [0°, 0°], with a given radius and precision.
33178 function circleStream(stream, radius, delta, direction, t0, t1) {
33179   if (!delta) return;
33180   var cosRadius = cos$1(radius),
33181       sinRadius = sin$1(radius),
33182       step = direction * delta;
33183   if (t0 == null) {
33184     t0 = radius + direction * tau$4;
33185     t1 = radius - step / 2;
33186   } else {
33187     t0 = circleRadius(cosRadius, t0);
33188     t1 = circleRadius(cosRadius, t1);
33189     if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$4;
33190   }
33191   for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
33192     point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]);
33193     stream.point(point[0], point[1]);
33194   }
33195 }
33196
33197 // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
33198 function circleRadius(cosRadius, point) {
33199   point = cartesian(point), point[0] -= cosRadius;
33200   cartesianNormalizeInPlace(point);
33201   var radius = acos(-point[1]);
33202   return ((-point[2] < 0 ? -radius : radius) + tau$4 - epsilon$4) % tau$4;
33203 }
33204
33205 var circle$1 = function() {
33206   var center = constant$13([0, 0]),
33207       radius = constant$13(90),
33208       precision = constant$13(6),
33209       ring,
33210       rotate,
33211       stream = {point: point};
33212
33213   function point(x, y) {
33214     ring.push(x = rotate(x, y));
33215     x[0] *= degrees$1, x[1] *= degrees$1;
33216   }
33217
33218   function circle() {
33219     var c = center.apply(this, arguments),
33220         r = radius.apply(this, arguments) * radians,
33221         p = precision.apply(this, arguments) * radians;
33222     ring = [];
33223     rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
33224     circleStream(stream, r, p, 1);
33225     c = {type: "Polygon", coordinates: [ring]};
33226     ring = rotate = null;
33227     return c;
33228   }
33229
33230   circle.center = function(_) {
33231     return arguments.length ? (center = typeof _ === "function" ? _ : constant$13([+_[0], +_[1]]), circle) : center;
33232   };
33233
33234   circle.radius = function(_) {
33235     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$13(+_), circle) : radius;
33236   };
33237
33238   circle.precision = function(_) {
33239     return arguments.length ? (precision = typeof _ === "function" ? _ : constant$13(+_), circle) : precision;
33240   };
33241
33242   return circle;
33243 };
33244
33245 var clipBuffer = function() {
33246   var lines = [],
33247       line;
33248   return {
33249     point: function(x, y) {
33250       line.push([x, y]);
33251     },
33252     lineStart: function() {
33253       lines.push(line = []);
33254     },
33255     lineEnd: noop$2,
33256     rejoin: function() {
33257       if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
33258     },
33259     result: function() {
33260       var result = lines;
33261       lines = [];
33262       line = null;
33263       return result;
33264     }
33265   };
33266 };
33267
33268 var clipLine = function(a, b, x0, y0, x1, y1) {
33269   var ax = a[0],
33270       ay = a[1],
33271       bx = b[0],
33272       by = b[1],
33273       t0 = 0,
33274       t1 = 1,
33275       dx = bx - ax,
33276       dy = by - ay,
33277       r;
33278
33279   r = x0 - ax;
33280   if (!dx && r > 0) return;
33281   r /= dx;
33282   if (dx < 0) {
33283     if (r < t0) return;
33284     if (r < t1) t1 = r;
33285   } else if (dx > 0) {
33286     if (r > t1) return;
33287     if (r > t0) t0 = r;
33288   }
33289
33290   r = x1 - ax;
33291   if (!dx && r < 0) return;
33292   r /= dx;
33293   if (dx < 0) {
33294     if (r > t1) return;
33295     if (r > t0) t0 = r;
33296   } else if (dx > 0) {
33297     if (r < t0) return;
33298     if (r < t1) t1 = r;
33299   }
33300
33301   r = y0 - ay;
33302   if (!dy && r > 0) return;
33303   r /= dy;
33304   if (dy < 0) {
33305     if (r < t0) return;
33306     if (r < t1) t1 = r;
33307   } else if (dy > 0) {
33308     if (r > t1) return;
33309     if (r > t0) t0 = r;
33310   }
33311
33312   r = y1 - ay;
33313   if (!dy && r < 0) return;
33314   r /= dy;
33315   if (dy < 0) {
33316     if (r > t1) return;
33317     if (r > t0) t0 = r;
33318   } else if (dy > 0) {
33319     if (r < t0) return;
33320     if (r < t1) t1 = r;
33321   }
33322
33323   if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
33324   if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
33325   return true;
33326 };
33327
33328 var pointEqual = function(a, b) {
33329   return abs(a[0] - b[0]) < epsilon$4 && abs(a[1] - b[1]) < epsilon$4;
33330 };
33331
33332 function Intersection(point, points, other, entry) {
33333   this.x = point;
33334   this.z = points;
33335   this.o = other; // another intersection
33336   this.e = entry; // is an entry?
33337   this.v = false; // visited
33338   this.n = this.p = null; // next & previous
33339 }
33340
33341 // A generalized polygon clipping algorithm: given a polygon that has been cut
33342 // into its visible line segments, and rejoins the segments by interpolating
33343 // along the clip edge.
33344 var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) {
33345   var subject = [],
33346       clip = [],
33347       i,
33348       n;
33349
33350   segments.forEach(function(segment) {
33351     if ((n = segment.length - 1) <= 0) return;
33352     var n, p0 = segment[0], p1 = segment[n], x;
33353
33354     // If the first and last points of a segment are coincident, then treat as a
33355     // closed ring. TODO if all rings are closed, then the winding order of the
33356     // exterior ring should be checked.
33357     if (pointEqual(p0, p1)) {
33358       stream.lineStart();
33359       for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
33360       stream.lineEnd();
33361       return;
33362     }
33363
33364     subject.push(x = new Intersection(p0, segment, null, true));
33365     clip.push(x.o = new Intersection(p0, null, x, false));
33366     subject.push(x = new Intersection(p1, segment, null, false));
33367     clip.push(x.o = new Intersection(p1, null, x, true));
33368   });
33369
33370   if (!subject.length) return;
33371
33372   clip.sort(compareIntersection);
33373   link$1(subject);
33374   link$1(clip);
33375
33376   for (i = 0, n = clip.length; i < n; ++i) {
33377     clip[i].e = startInside = !startInside;
33378   }
33379
33380   var start = subject[0],
33381       points,
33382       point;
33383
33384   while (1) {
33385     // Find first unvisited intersection.
33386     var current = start,
33387         isSubject = true;
33388     while (current.v) if ((current = current.n) === start) return;
33389     points = current.z;
33390     stream.lineStart();
33391     do {
33392       current.v = current.o.v = true;
33393       if (current.e) {
33394         if (isSubject) {
33395           for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
33396         } else {
33397           interpolate(current.x, current.n.x, 1, stream);
33398         }
33399         current = current.n;
33400       } else {
33401         if (isSubject) {
33402           points = current.p.z;
33403           for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
33404         } else {
33405           interpolate(current.x, current.p.x, -1, stream);
33406         }
33407         current = current.p;
33408       }
33409       current = current.o;
33410       points = current.z;
33411       isSubject = !isSubject;
33412     } while (!current.v);
33413     stream.lineEnd();
33414   }
33415 };
33416
33417 function link$1(array) {
33418   if (!(n = array.length)) return;
33419   var n,
33420       i = 0,
33421       a = array[0],
33422       b;
33423   while (++i < n) {
33424     a.n = b = array[i];
33425     b.p = a;
33426     a = b;
33427   }
33428   a.n = b = array[0];
33429   b.p = a;
33430 }
33431
33432 var clipMax = 1e9;
33433 var clipMin = -clipMax;
33434
33435 // TODO Use d3-polygon’s polygonContains here for the ring check?
33436 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
33437
33438 function clipExtent(x0, y0, x1, y1) {
33439
33440   function visible(x, y) {
33441     return x0 <= x && x <= x1 && y0 <= y && y <= y1;
33442   }
33443
33444   function interpolate(from, to, direction, stream) {
33445     var a = 0, a1 = 0;
33446     if (from == null
33447         || (a = corner(from, direction)) !== (a1 = corner(to, direction))
33448         || comparePoint(from, to) < 0 ^ direction > 0) {
33449       do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
33450       while ((a = (a + direction + 4) % 4) !== a1);
33451     } else {
33452       stream.point(to[0], to[1]);
33453     }
33454   }
33455
33456   function corner(p, direction) {
33457     return abs(p[0] - x0) < epsilon$4 ? direction > 0 ? 0 : 3
33458         : abs(p[0] - x1) < epsilon$4 ? direction > 0 ? 2 : 1
33459         : abs(p[1] - y0) < epsilon$4 ? direction > 0 ? 1 : 0
33460         : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
33461   }
33462
33463   function compareIntersection(a, b) {
33464     return comparePoint(a.x, b.x);
33465   }
33466
33467   function comparePoint(a, b) {
33468     var ca = corner(a, 1),
33469         cb = corner(b, 1);
33470     return ca !== cb ? ca - cb
33471         : ca === 0 ? b[1] - a[1]
33472         : ca === 1 ? a[0] - b[0]
33473         : ca === 2 ? a[1] - b[1]
33474         : b[0] - a[0];
33475   }
33476
33477   return function(stream) {
33478     var activeStream = stream,
33479         bufferStream = clipBuffer(),
33480         segments,
33481         polygon,
33482         ring,
33483         x__, y__, v__, // first point
33484         x_, y_, v_, // previous point
33485         first,
33486         clean;
33487
33488     var clipStream = {
33489       point: point,
33490       lineStart: lineStart,
33491       lineEnd: lineEnd,
33492       polygonStart: polygonStart,
33493       polygonEnd: polygonEnd
33494     };
33495
33496     function point(x, y) {
33497       if (visible(x, y)) activeStream.point(x, y);
33498     }
33499
33500     function polygonInside() {
33501       var winding = 0;
33502
33503       for (var i = 0, n = polygon.length; i < n; ++i) {
33504         for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
33505           a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
33506           if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
33507           else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
33508         }
33509       }
33510
33511       return winding;
33512     }
33513
33514     // Buffer geometry within a polygon and then clip it en masse.
33515     function polygonStart() {
33516       activeStream = bufferStream, segments = [], polygon = [], clean = true;
33517     }
33518
33519     function polygonEnd() {
33520       var startInside = polygonInside(),
33521           cleanInside = clean && startInside,
33522           visible = (segments = merge(segments)).length;
33523       if (cleanInside || visible) {
33524         stream.polygonStart();
33525         if (cleanInside) {
33526           stream.lineStart();
33527           interpolate(null, null, 1, stream);
33528           stream.lineEnd();
33529         }
33530         if (visible) {
33531           clipPolygon(segments, compareIntersection, startInside, interpolate, stream);
33532         }
33533         stream.polygonEnd();
33534       }
33535       activeStream = stream, segments = polygon = ring = null;
33536     }
33537
33538     function lineStart() {
33539       clipStream.point = linePoint;
33540       if (polygon) polygon.push(ring = []);
33541       first = true;
33542       v_ = false;
33543       x_ = y_ = NaN;
33544     }
33545
33546     // TODO rather than special-case polygons, simply handle them separately.
33547     // Ideally, coincident intersection points should be jittered to avoid
33548     // clipping issues.
33549     function lineEnd() {
33550       if (segments) {
33551         linePoint(x__, y__);
33552         if (v__ && v_) bufferStream.rejoin();
33553         segments.push(bufferStream.result());
33554       }
33555       clipStream.point = point;
33556       if (v_) activeStream.lineEnd();
33557     }
33558
33559     function linePoint(x, y) {
33560       var v = visible(x, y);
33561       if (polygon) ring.push([x, y]);
33562       if (first) {
33563         x__ = x, y__ = y, v__ = v;
33564         first = false;
33565         if (v) {
33566           activeStream.lineStart();
33567           activeStream.point(x, y);
33568         }
33569       } else {
33570         if (v && v_) activeStream.point(x, y);
33571         else {
33572           var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
33573               b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
33574           if (clipLine(a, b, x0, y0, x1, y1)) {
33575             if (!v_) {
33576               activeStream.lineStart();
33577               activeStream.point(a[0], a[1]);
33578             }
33579             activeStream.point(b[0], b[1]);
33580             if (!v) activeStream.lineEnd();
33581             clean = false;
33582           } else if (v) {
33583             activeStream.lineStart();
33584             activeStream.point(x, y);
33585             clean = false;
33586           }
33587         }
33588       }
33589       x_ = x, y_ = y, v_ = v;
33590     }
33591
33592     return clipStream;
33593   };
33594 }
33595
33596 var extent$1 = function() {
33597   var x0 = 0,
33598       y0 = 0,
33599       x1 = 960,
33600       y1 = 500,
33601       cache,
33602       cacheStream,
33603       clip;
33604
33605   return clip = {
33606     stream: function(stream) {
33607       return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream);
33608     },
33609     extent: function(_) {
33610       return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
33611     }
33612   };
33613 };
33614
33615 var lengthSum = adder();
33616 var lambda0$2;
33617 var sinPhi0$1;
33618 var cosPhi0$1;
33619
33620 var lengthStream = {
33621   sphere: noop$2,
33622   point: noop$2,
33623   lineStart: lengthLineStart,
33624   lineEnd: noop$2,
33625   polygonStart: noop$2,
33626   polygonEnd: noop$2
33627 };
33628
33629 function lengthLineStart() {
33630   lengthStream.point = lengthPointFirst;
33631   lengthStream.lineEnd = lengthLineEnd;
33632 }
33633
33634 function lengthLineEnd() {
33635   lengthStream.point = lengthStream.lineEnd = noop$2;
33636 }
33637
33638 function lengthPointFirst(lambda, phi) {
33639   lambda *= radians, phi *= radians;
33640   lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi);
33641   lengthStream.point = lengthPoint;
33642 }
33643
33644 function lengthPoint(lambda, phi) {
33645   lambda *= radians, phi *= radians;
33646   var sinPhi = sin$1(phi),
33647       cosPhi = cos$1(phi),
33648       delta = abs(lambda - lambda0$2),
33649       cosDelta = cos$1(delta),
33650       sinDelta = sin$1(delta),
33651       x = cosPhi * sinDelta,
33652       y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta,
33653       z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta;
33654   lengthSum.add(atan2(sqrt$1(x * x + y * y), z));
33655   lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi;
33656 }
33657
33658 var d3GeoLength = function(object) {
33659   lengthSum.reset();
33660   geoStream(object, lengthStream);
33661   return +lengthSum;
33662 };
33663
33664 var coordinates = [null, null];
33665 var object$1 = {type: "LineString", coordinates: coordinates};
33666
33667 var distance = function(a, b) {
33668   coordinates[0] = a;
33669   coordinates[1] = b;
33670   return d3GeoLength(object$1);
33671 };
33672
33673 function graticuleX(y0, y1, dy) {
33674   var y = range(y0, y1 - epsilon$4, dy).concat(y1);
33675   return function(x) { return y.map(function(y) { return [x, y]; }); };
33676 }
33677
33678 function graticuleY(x0, x1, dx) {
33679   var x = range(x0, x1 - epsilon$4, dx).concat(x1);
33680   return function(y) { return x.map(function(x) { return [x, y]; }); };
33681 }
33682
33683 function graticule() {
33684   var x1, x0, X1, X0,
33685       y1, y0, Y1, Y0,
33686       dx = 10, dy = dx, DX = 90, DY = 360,
33687       x, y, X, Y,
33688       precision = 2.5;
33689
33690   function graticule() {
33691     return {type: "MultiLineString", coordinates: lines()};
33692   }
33693
33694   function lines() {
33695     return range(ceil(X0 / DX) * DX, X1, DX).map(X)
33696         .concat(range(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
33697         .concat(range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$4; }).map(x))
33698         .concat(range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$4; }).map(y));
33699   }
33700
33701   graticule.lines = function() {
33702     return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
33703   };
33704
33705   graticule.outline = function() {
33706     return {
33707       type: "Polygon",
33708       coordinates: [
33709         X(X0).concat(
33710         Y(Y1).slice(1),
33711         X(X1).reverse().slice(1),
33712         Y(Y0).reverse().slice(1))
33713       ]
33714     };
33715   };
33716
33717   graticule.extent = function(_) {
33718     if (!arguments.length) return graticule.extentMinor();
33719     return graticule.extentMajor(_).extentMinor(_);
33720   };
33721
33722   graticule.extentMajor = 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.extentMinor = function(_) {
33732     if (!arguments.length) return [[x0, y0], [x1, y1]];
33733     x0 = +_[0][0], x1 = +_[1][0];
33734     y0 = +_[0][1], y1 = +_[1][1];
33735     if (x0 > x1) _ = x0, x0 = x1, x1 = _;
33736     if (y0 > y1) _ = y0, y0 = y1, y1 = _;
33737     return graticule.precision(precision);
33738   };
33739
33740   graticule.step = function(_) {
33741     if (!arguments.length) return graticule.stepMinor();
33742     return graticule.stepMajor(_).stepMinor(_);
33743   };
33744
33745   graticule.stepMajor = function(_) {
33746     if (!arguments.length) return [DX, DY];
33747     DX = +_[0], DY = +_[1];
33748     return graticule;
33749   };
33750
33751   graticule.stepMinor = function(_) {
33752     if (!arguments.length) return [dx, dy];
33753     dx = +_[0], dy = +_[1];
33754     return graticule;
33755   };
33756
33757   graticule.precision = function(_) {
33758     if (!arguments.length) return precision;
33759     precision = +_;
33760     x = graticuleX(y0, y1, 90);
33761     y = graticuleY(x0, x1, precision);
33762     X = graticuleX(Y0, Y1, 90);
33763     Y = graticuleY(X0, X1, precision);
33764     return graticule;
33765   };
33766
33767   return graticule
33768       .extentMajor([[-180, -90 + epsilon$4], [180, 90 - epsilon$4]])
33769       .extentMinor([[-180, -80 - epsilon$4], [180, 80 + epsilon$4]]);
33770 }
33771
33772 function graticule10() {
33773   return graticule()();
33774 }
33775
33776 var interpolate$2 = function(a, b) {
33777   var x0 = a[0] * radians,
33778       y0 = a[1] * radians,
33779       x1 = b[0] * radians,
33780       y1 = b[1] * radians,
33781       cy0 = cos$1(y0),
33782       sy0 = sin$1(y0),
33783       cy1 = cos$1(y1),
33784       sy1 = sin$1(y1),
33785       kx0 = cy0 * cos$1(x0),
33786       ky0 = cy0 * sin$1(x0),
33787       kx1 = cy1 * cos$1(x1),
33788       ky1 = cy1 * sin$1(x1),
33789       d = 2 * asin$1(sqrt$1(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
33790       k = sin$1(d);
33791
33792   var interpolate = d ? function(t) {
33793     var B = sin$1(t *= d) / k,
33794         A = sin$1(d - t) / k,
33795         x = A * kx0 + B * kx1,
33796         y = A * ky0 + B * ky1,
33797         z = A * sy0 + B * sy1;
33798     return [
33799       atan2(y, x) * degrees$1,
33800       atan2(z, sqrt$1(x * x + y * y)) * degrees$1
33801     ];
33802   } : function() {
33803     return [x0 * degrees$1, y0 * degrees$1];
33804   };
33805
33806   interpolate.distance = d;
33807
33808   return interpolate;
33809 };
33810
33811 var identity$7 = function(x) {
33812   return x;
33813 };
33814
33815 var areaSum$1 = adder();
33816 var areaRingSum$1 = adder();
33817 var x00;
33818 var y00;
33819 var x0$1;
33820 var y0$1;
33821
33822 var areaStream$1 = {
33823   point: noop$2,
33824   lineStart: noop$2,
33825   lineEnd: noop$2,
33826   polygonStart: function() {
33827     areaStream$1.lineStart = areaRingStart$1;
33828     areaStream$1.lineEnd = areaRingEnd$1;
33829   },
33830   polygonEnd: function() {
33831     areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$2;
33832     areaSum$1.add(abs(areaRingSum$1));
33833     areaRingSum$1.reset();
33834   },
33835   result: function() {
33836     var area = areaSum$1 / 2;
33837     areaSum$1.reset();
33838     return area;
33839   }
33840 };
33841
33842 function areaRingStart$1() {
33843   areaStream$1.point = areaPointFirst$1;
33844 }
33845
33846 function areaPointFirst$1(x, y) {
33847   areaStream$1.point = areaPoint$1;
33848   x00 = x0$1 = x, y00 = y0$1 = y;
33849 }
33850
33851 function areaPoint$1(x, y) {
33852   areaRingSum$1.add(y0$1 * x - x0$1 * y);
33853   x0$1 = x, y0$1 = y;
33854 }
33855
33856 function areaRingEnd$1() {
33857   areaPoint$1(x00, y00);
33858 }
33859
33860 var x0$2 = Infinity;
33861 var y0$2 = x0$2;
33862 var x1 = -x0$2;
33863 var y1 = x1;
33864
33865 var boundsStream$1 = {
33866   point: boundsPoint$1,
33867   lineStart: noop$2,
33868   lineEnd: noop$2,
33869   polygonStart: noop$2,
33870   polygonEnd: noop$2,
33871   result: function() {
33872     var bounds = [[x0$2, y0$2], [x1, y1]];
33873     x1 = y1 = -(y0$2 = x0$2 = Infinity);
33874     return bounds;
33875   }
33876 };
33877
33878 function boundsPoint$1(x, y) {
33879   if (x < x0$2) x0$2 = x;
33880   if (x > x1) x1 = x;
33881   if (y < y0$2) y0$2 = y;
33882   if (y > y1) y1 = y;
33883 }
33884
33885 // TODO Enforce positive area for exterior, negative area for interior?
33886
33887 var X0$1 = 0;
33888 var Y0$1 = 0;
33889 var Z0$1 = 0;
33890 var X1$1 = 0;
33891 var Y1$1 = 0;
33892 var Z1$1 = 0;
33893 var X2$1 = 0;
33894 var Y2$1 = 0;
33895 var Z2$1 = 0;
33896 var x00$1;
33897 var y00$1;
33898 var x0$3;
33899 var y0$3;
33900
33901 var centroidStream$1 = {
33902   point: centroidPoint$1,
33903   lineStart: centroidLineStart$1,
33904   lineEnd: centroidLineEnd$1,
33905   polygonStart: function() {
33906     centroidStream$1.lineStart = centroidRingStart$1;
33907     centroidStream$1.lineEnd = centroidRingEnd$1;
33908   },
33909   polygonEnd: function() {
33910     centroidStream$1.point = centroidPoint$1;
33911     centroidStream$1.lineStart = centroidLineStart$1;
33912     centroidStream$1.lineEnd = centroidLineEnd$1;
33913   },
33914   result: function() {
33915     var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1]
33916         : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1]
33917         : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1]
33918         : [NaN, NaN];
33919     X0$1 = Y0$1 = Z0$1 =
33920     X1$1 = Y1$1 = Z1$1 =
33921     X2$1 = Y2$1 = Z2$1 = 0;
33922     return centroid;
33923   }
33924 };
33925
33926 function centroidPoint$1(x, y) {
33927   X0$1 += x;
33928   Y0$1 += y;
33929   ++Z0$1;
33930 }
33931
33932 function centroidLineStart$1() {
33933   centroidStream$1.point = centroidPointFirstLine;
33934 }
33935
33936 function centroidPointFirstLine(x, y) {
33937   centroidStream$1.point = centroidPointLine;
33938   centroidPoint$1(x0$3 = x, y0$3 = y);
33939 }
33940
33941 function centroidPointLine(x, y) {
33942   var dx = x - x0$3, dy = y - y0$3, z = sqrt$1(dx * dx + dy * dy);
33943   X1$1 += z * (x0$3 + x) / 2;
33944   Y1$1 += z * (y0$3 + y) / 2;
33945   Z1$1 += z;
33946   centroidPoint$1(x0$3 = x, y0$3 = y);
33947 }
33948
33949 function centroidLineEnd$1() {
33950   centroidStream$1.point = centroidPoint$1;
33951 }
33952
33953 function centroidRingStart$1() {
33954   centroidStream$1.point = centroidPointFirstRing;
33955 }
33956
33957 function centroidRingEnd$1() {
33958   centroidPointRing(x00$1, y00$1);
33959 }
33960
33961 function centroidPointFirstRing(x, y) {
33962   centroidStream$1.point = centroidPointRing;
33963   centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y);
33964 }
33965
33966 function centroidPointRing(x, y) {
33967   var dx = x - x0$3,
33968       dy = y - y0$3,
33969       z = sqrt$1(dx * dx + dy * dy);
33970
33971   X1$1 += z * (x0$3 + x) / 2;
33972   Y1$1 += z * (y0$3 + y) / 2;
33973   Z1$1 += z;
33974
33975   z = y0$3 * x - x0$3 * y;
33976   X2$1 += z * (x0$3 + x);
33977   Y2$1 += z * (y0$3 + y);
33978   Z2$1 += z * 3;
33979   centroidPoint$1(x0$3 = x, y0$3 = y);
33980 }
33981
33982 function PathContext(context) {
33983   this._context = context;
33984 }
33985
33986 PathContext.prototype = {
33987   _radius: 4.5,
33988   pointRadius: function(_) {
33989     return this._radius = _, this;
33990   },
33991   polygonStart: function() {
33992     this._line = 0;
33993   },
33994   polygonEnd: function() {
33995     this._line = NaN;
33996   },
33997   lineStart: function() {
33998     this._point = 0;
33999   },
34000   lineEnd: function() {
34001     if (this._line === 0) this._context.closePath();
34002     this._point = NaN;
34003   },
34004   point: function(x, y) {
34005     switch (this._point) {
34006       case 0: {
34007         this._context.moveTo(x, y);
34008         this._point = 1;
34009         break;
34010       }
34011       case 1: {
34012         this._context.lineTo(x, y);
34013         break;
34014       }
34015       default: {
34016         this._context.moveTo(x + this._radius, y);
34017         this._context.arc(x, y, this._radius, 0, tau$4);
34018         break;
34019       }
34020     }
34021   },
34022   result: noop$2
34023 };
34024
34025 function PathString() {
34026   this._string = [];
34027 }
34028
34029 PathString.prototype = {
34030   _circle: circle$2(4.5),
34031   pointRadius: function(_) {
34032     return this._circle = circle$2(_), this;
34033   },
34034   polygonStart: function() {
34035     this._line = 0;
34036   },
34037   polygonEnd: function() {
34038     this._line = NaN;
34039   },
34040   lineStart: function() {
34041     this._point = 0;
34042   },
34043   lineEnd: function() {
34044     if (this._line === 0) this._string.push("Z");
34045     this._point = NaN;
34046   },
34047   point: function(x, y) {
34048     switch (this._point) {
34049       case 0: {
34050         this._string.push("M", x, ",", y);
34051         this._point = 1;
34052         break;
34053       }
34054       case 1: {
34055         this._string.push("L", x, ",", y);
34056         break;
34057       }
34058       default: {
34059         this._string.push("M", x, ",", y, this._circle);
34060         break;
34061       }
34062     }
34063   },
34064   result: function() {
34065     if (this._string.length) {
34066       var result = this._string.join("");
34067       this._string = [];
34068       return result;
34069     }
34070   }
34071 };
34072
34073 function circle$2(radius) {
34074   return "m0," + radius
34075       + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
34076       + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
34077       + "z";
34078 }
34079
34080 var index$5 = function(projection, context) {
34081   var pointRadius = 4.5,
34082       projectionStream,
34083       contextStream;
34084
34085   function path(object) {
34086     if (object) {
34087       if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
34088       geoStream(object, projectionStream(contextStream));
34089     }
34090     return contextStream.result();
34091   }
34092
34093   path.area = function(object) {
34094     geoStream(object, projectionStream(areaStream$1));
34095     return areaStream$1.result();
34096   };
34097
34098   path.bounds = function(object) {
34099     geoStream(object, projectionStream(boundsStream$1));
34100     return boundsStream$1.result();
34101   };
34102
34103   path.centroid = function(object) {
34104     geoStream(object, projectionStream(centroidStream$1));
34105     return centroidStream$1.result();
34106   };
34107
34108   path.projection = function(_) {
34109     return arguments.length ? (projectionStream = (projection = _) == null ? identity$7 : _.stream, path) : projection;
34110   };
34111
34112   path.context = function(_) {
34113     if (!arguments.length) return context;
34114     contextStream = (context = _) == null ? new PathString : new PathContext(_);
34115     if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
34116     return path;
34117   };
34118
34119   path.pointRadius = function(_) {
34120     if (!arguments.length) return pointRadius;
34121     pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
34122     return path;
34123   };
34124
34125   return path.projection(projection).context(context);
34126 };
34127
34128 var sum$2 = adder();
34129
34130 var polygonContains = function(polygon, point) {
34131   var lambda = point[0],
34132       phi = point[1],
34133       normal = [sin$1(lambda), -cos$1(lambda), 0],
34134       angle = 0,
34135       winding = 0;
34136
34137   sum$2.reset();
34138
34139   for (var i = 0, n = polygon.length; i < n; ++i) {
34140     if (!(m = (ring = polygon[i]).length)) continue;
34141     var ring,
34142         m,
34143         point0 = ring[m - 1],
34144         lambda0 = point0[0],
34145         phi0 = point0[1] / 2 + quarterPi,
34146         sinPhi0 = sin$1(phi0),
34147         cosPhi0 = cos$1(phi0);
34148
34149     for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
34150       var point1 = ring[j],
34151           lambda1 = point1[0],
34152           phi1 = point1[1] / 2 + quarterPi,
34153           sinPhi1 = sin$1(phi1),
34154           cosPhi1 = cos$1(phi1),
34155           delta = lambda1 - lambda0,
34156           sign$$1 = delta >= 0 ? 1 : -1,
34157           absDelta = sign$$1 * delta,
34158           antimeridian = absDelta > pi$4,
34159           k = sinPhi0 * sinPhi1;
34160
34161       sum$2.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta)));
34162       angle += antimeridian ? delta + sign$$1 * tau$4 : delta;
34163
34164       // Are the longitudes either side of the point’s meridian (lambda),
34165       // and are the latitudes smaller than the parallel (phi)?
34166       if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
34167         var arc = cartesianCross(cartesian(point0), cartesian(point1));
34168         cartesianNormalizeInPlace(arc);
34169         var intersection = cartesianCross(normal, arc);
34170         cartesianNormalizeInPlace(intersection);
34171         var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin$1(intersection[2]);
34172         if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
34173           winding += antimeridian ^ delta >= 0 ? 1 : -1;
34174         }
34175       }
34176     }
34177   }
34178
34179   // First, determine whether the South pole is inside or outside:
34180   //
34181   // It is inside if:
34182   // * the polygon winds around it in a clockwise direction.
34183   // * the polygon does not (cumulatively) wind around it, but has a negative
34184   //   (counter-clockwise) area.
34185   //
34186   // Second, count the (signed) number of times a segment crosses a lambda
34187   // from the point to the South pole.  If it is zero, then the point is the
34188   // same side as the South pole.
34189
34190   return (angle < -epsilon$4 || angle < epsilon$4 && sum$2 < -epsilon$4) ^ (winding & 1);
34191 };
34192
34193 var clip = function(pointVisible, clipLine, interpolate, start) {
34194   return function(rotate, sink) {
34195     var line = clipLine(sink),
34196         rotatedStart = rotate.invert(start[0], start[1]),
34197         ringBuffer = clipBuffer(),
34198         ringSink = clipLine(ringBuffer),
34199         polygonStarted = false,
34200         polygon,
34201         segments,
34202         ring;
34203
34204     var clip = {
34205       point: point,
34206       lineStart: lineStart,
34207       lineEnd: lineEnd,
34208       polygonStart: function() {
34209         clip.point = pointRing;
34210         clip.lineStart = ringStart;
34211         clip.lineEnd = ringEnd;
34212         segments = [];
34213         polygon = [];
34214       },
34215       polygonEnd: function() {
34216         clip.point = point;
34217         clip.lineStart = lineStart;
34218         clip.lineEnd = lineEnd;
34219         segments = merge(segments);
34220         var startInside = polygonContains(polygon, rotatedStart);
34221         if (segments.length) {
34222           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34223           clipPolygon(segments, compareIntersection, startInside, interpolate, sink);
34224         } else if (startInside) {
34225           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34226           sink.lineStart();
34227           interpolate(null, null, 1, sink);
34228           sink.lineEnd();
34229         }
34230         if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
34231         segments = polygon = null;
34232       },
34233       sphere: function() {
34234         sink.polygonStart();
34235         sink.lineStart();
34236         interpolate(null, null, 1, sink);
34237         sink.lineEnd();
34238         sink.polygonEnd();
34239       }
34240     };
34241
34242     function point(lambda, phi) {
34243       var point = rotate(lambda, phi);
34244       if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
34245     }
34246
34247     function pointLine(lambda, phi) {
34248       var point = rotate(lambda, phi);
34249       line.point(point[0], point[1]);
34250     }
34251
34252     function lineStart() {
34253       clip.point = pointLine;
34254       line.lineStart();
34255     }
34256
34257     function lineEnd() {
34258       clip.point = point;
34259       line.lineEnd();
34260     }
34261
34262     function pointRing(lambda, phi) {
34263       ring.push([lambda, phi]);
34264       var point = rotate(lambda, phi);
34265       ringSink.point(point[0], point[1]);
34266     }
34267
34268     function ringStart() {
34269       ringSink.lineStart();
34270       ring = [];
34271     }
34272
34273     function ringEnd() {
34274       pointRing(ring[0][0], ring[0][1]);
34275       ringSink.lineEnd();
34276
34277       var clean = ringSink.clean(),
34278           ringSegments = ringBuffer.result(),
34279           i, n = ringSegments.length, m,
34280           segment,
34281           point;
34282
34283       ring.pop();
34284       polygon.push(ring);
34285       ring = null;
34286
34287       if (!n) return;
34288
34289       // No intersections.
34290       if (clean & 1) {
34291         segment = ringSegments[0];
34292         if ((m = segment.length - 1) > 0) {
34293           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34294           sink.lineStart();
34295           for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
34296           sink.lineEnd();
34297         }
34298         return;
34299       }
34300
34301       // Rejoin connected segments.
34302       // TODO reuse ringBuffer.rejoin()?
34303       if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
34304
34305       segments.push(ringSegments.filter(validSegment));
34306     }
34307
34308     return clip;
34309   };
34310 };
34311
34312 function validSegment(segment) {
34313   return segment.length > 1;
34314 }
34315
34316 // Intersections are sorted along the clip edge. For both antimeridian cutting
34317 // and circle clipping, the same comparison is used.
34318 function compareIntersection(a, b) {
34319   return ((a = a.x)[0] < 0 ? a[1] - halfPi$3 - epsilon$4 : halfPi$3 - a[1])
34320        - ((b = b.x)[0] < 0 ? b[1] - halfPi$3 - epsilon$4 : halfPi$3 - b[1]);
34321 }
34322
34323 var clipAntimeridian = clip(
34324   function() { return true; },
34325   clipAntimeridianLine,
34326   clipAntimeridianInterpolate,
34327   [-pi$4, -halfPi$3]
34328 );
34329
34330 // Takes a line and cuts into visible segments. Return values: 0 - there were
34331 // intersections or the line was empty; 1 - no intersections; 2 - there were
34332 // intersections, and the first and last segments should be rejoined.
34333 function clipAntimeridianLine(stream) {
34334   var lambda0 = NaN,
34335       phi0 = NaN,
34336       sign0 = NaN,
34337       clean; // no intersections
34338
34339   return {
34340     lineStart: function() {
34341       stream.lineStart();
34342       clean = 1;
34343     },
34344     point: function(lambda1, phi1) {
34345       var sign1 = lambda1 > 0 ? pi$4 : -pi$4,
34346           delta = abs(lambda1 - lambda0);
34347       if (abs(delta - pi$4) < epsilon$4) { // line crosses a pole
34348         stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$3 : -halfPi$3);
34349         stream.point(sign0, phi0);
34350         stream.lineEnd();
34351         stream.lineStart();
34352         stream.point(sign1, phi0);
34353         stream.point(lambda1, phi0);
34354         clean = 0;
34355       } else if (sign0 !== sign1 && delta >= pi$4) { // line crosses antimeridian
34356         if (abs(lambda0 - sign0) < epsilon$4) lambda0 -= sign0 * epsilon$4; // handle degeneracies
34357         if (abs(lambda1 - sign1) < epsilon$4) lambda1 -= sign1 * epsilon$4;
34358         phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
34359         stream.point(sign0, phi0);
34360         stream.lineEnd();
34361         stream.lineStart();
34362         stream.point(sign1, phi0);
34363         clean = 0;
34364       }
34365       stream.point(lambda0 = lambda1, phi0 = phi1);
34366       sign0 = sign1;
34367     },
34368     lineEnd: function() {
34369       stream.lineEnd();
34370       lambda0 = phi0 = NaN;
34371     },
34372     clean: function() {
34373       return 2 - clean; // if intersections, rejoin first and last segments
34374     }
34375   };
34376 }
34377
34378 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
34379   var cosPhi0,
34380       cosPhi1,
34381       sinLambda0Lambda1 = sin$1(lambda0 - lambda1);
34382   return abs(sinLambda0Lambda1) > epsilon$4
34383       ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1)
34384           - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0))
34385           / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
34386       : (phi0 + phi1) / 2;
34387 }
34388
34389 function clipAntimeridianInterpolate(from, to, direction, stream) {
34390   var phi;
34391   if (from == null) {
34392     phi = direction * halfPi$3;
34393     stream.point(-pi$4, phi);
34394     stream.point(0, phi);
34395     stream.point(pi$4, phi);
34396     stream.point(pi$4, 0);
34397     stream.point(pi$4, -phi);
34398     stream.point(0, -phi);
34399     stream.point(-pi$4, -phi);
34400     stream.point(-pi$4, 0);
34401     stream.point(-pi$4, phi);
34402   } else if (abs(from[0] - to[0]) > epsilon$4) {
34403     var lambda = from[0] < to[0] ? pi$4 : -pi$4;
34404     phi = direction * lambda / 2;
34405     stream.point(-lambda, phi);
34406     stream.point(0, phi);
34407     stream.point(lambda, phi);
34408   } else {
34409     stream.point(to[0], to[1]);
34410   }
34411 }
34412
34413 var clipCircle = function(radius, delta) {
34414   var cr = cos$1(radius),
34415       smallRadius = cr > 0,
34416       notHemisphere = abs(cr) > epsilon$4; // TODO optimise for this common case
34417
34418   function interpolate(from, to, direction, stream) {
34419     circleStream(stream, radius, delta, direction, from, to);
34420   }
34421
34422   function visible(lambda, phi) {
34423     return cos$1(lambda) * cos$1(phi) > cr;
34424   }
34425
34426   // Takes a line and cuts into visible segments. Return values used for polygon
34427   // clipping: 0 - there were intersections or the line was empty; 1 - no
34428   // intersections 2 - there were intersections, and the first and last segments
34429   // should be rejoined.
34430   function clipLine(stream) {
34431     var point0, // previous point
34432         c0, // code for previous point
34433         v0, // visibility of previous point
34434         v00, // visibility of first point
34435         clean; // no intersections
34436     return {
34437       lineStart: function() {
34438         v00 = v0 = false;
34439         clean = 1;
34440       },
34441       point: function(lambda, phi) {
34442         var point1 = [lambda, phi],
34443             point2,
34444             v = visible(lambda, phi),
34445             c = smallRadius
34446               ? v ? 0 : code(lambda, phi)
34447               : v ? code(lambda + (lambda < 0 ? pi$4 : -pi$4), phi) : 0;
34448         if (!point0 && (v00 = v0 = v)) stream.lineStart();
34449         // Handle degeneracies.
34450         // TODO ignore if not clipping polygons.
34451         if (v !== v0) {
34452           point2 = intersect(point0, point1);
34453           if (pointEqual(point0, point2) || pointEqual(point1, point2)) {
34454             point1[0] += epsilon$4;
34455             point1[1] += epsilon$4;
34456             v = visible(point1[0], point1[1]);
34457           }
34458         }
34459         if (v !== v0) {
34460           clean = 0;
34461           if (v) {
34462             // outside going in
34463             stream.lineStart();
34464             point2 = intersect(point1, point0);
34465             stream.point(point2[0], point2[1]);
34466           } else {
34467             // inside going out
34468             point2 = intersect(point0, point1);
34469             stream.point(point2[0], point2[1]);
34470             stream.lineEnd();
34471           }
34472           point0 = point2;
34473         } else if (notHemisphere && point0 && smallRadius ^ v) {
34474           var t;
34475           // If the codes for two points are different, or are both zero,
34476           // and there this segment intersects with the small circle.
34477           if (!(c & c0) && (t = intersect(point1, point0, true))) {
34478             clean = 0;
34479             if (smallRadius) {
34480               stream.lineStart();
34481               stream.point(t[0][0], t[0][1]);
34482               stream.point(t[1][0], t[1][1]);
34483               stream.lineEnd();
34484             } else {
34485               stream.point(t[1][0], t[1][1]);
34486               stream.lineEnd();
34487               stream.lineStart();
34488               stream.point(t[0][0], t[0][1]);
34489             }
34490           }
34491         }
34492         if (v && (!point0 || !pointEqual(point0, point1))) {
34493           stream.point(point1[0], point1[1]);
34494         }
34495         point0 = point1, v0 = v, c0 = c;
34496       },
34497       lineEnd: function() {
34498         if (v0) stream.lineEnd();
34499         point0 = null;
34500       },
34501       // Rejoin first and last segments if there were intersections and the first
34502       // and last points were visible.
34503       clean: function() {
34504         return clean | ((v00 && v0) << 1);
34505       }
34506     };
34507   }
34508
34509   // Intersects the great circle between a and b with the clip circle.
34510   function intersect(a, b, two) {
34511     var pa = cartesian(a),
34512         pb = cartesian(b);
34513
34514     // We have two planes, n1.p = d1 and n2.p = d2.
34515     // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
34516     var n1 = [1, 0, 0], // normal
34517         n2 = cartesianCross(pa, pb),
34518         n2n2 = cartesianDot(n2, n2),
34519         n1n2 = n2[0], // cartesianDot(n1, n2),
34520         determinant = n2n2 - n1n2 * n1n2;
34521
34522     // Two polar points.
34523     if (!determinant) return !two && a;
34524
34525     var c1 =  cr * n2n2 / determinant,
34526         c2 = -cr * n1n2 / determinant,
34527         n1xn2 = cartesianCross(n1, n2),
34528         A = cartesianScale(n1, c1),
34529         B = cartesianScale(n2, c2);
34530     cartesianAddInPlace(A, B);
34531
34532     // Solve |p(t)|^2 = 1.
34533     var u = n1xn2,
34534         w = cartesianDot(A, u),
34535         uu = cartesianDot(u, u),
34536         t2 = w * w - uu * (cartesianDot(A, A) - 1);
34537
34538     if (t2 < 0) return;
34539
34540     var t = sqrt$1(t2),
34541         q = cartesianScale(u, (-w - t) / uu);
34542     cartesianAddInPlace(q, A);
34543     q = spherical(q);
34544
34545     if (!two) return q;
34546
34547     // Two intersection points.
34548     var lambda0 = a[0],
34549         lambda1 = b[0],
34550         phi0 = a[1],
34551         phi1 = b[1],
34552         z;
34553
34554     if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
34555
34556     var delta = lambda1 - lambda0,
34557         polar = abs(delta - pi$4) < epsilon$4,
34558         meridian = polar || delta < epsilon$4;
34559
34560     if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
34561
34562     // Check that the first point is between a and b.
34563     if (meridian
34564         ? polar
34565           ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$4 ? phi0 : phi1)
34566           : phi0 <= q[1] && q[1] <= phi1
34567         : delta > pi$4 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
34568       var q1 = cartesianScale(u, (-w + t) / uu);
34569       cartesianAddInPlace(q1, A);
34570       return [q, spherical(q1)];
34571     }
34572   }
34573
34574   // Generates a 4-bit vector representing the location of a point relative to
34575   // the small circle's bounding box.
34576   function code(lambda, phi) {
34577     var r = smallRadius ? radius : pi$4 - radius,
34578         code = 0;
34579     if (lambda < -r) code |= 1; // left
34580     else if (lambda > r) code |= 2; // right
34581     if (phi < -r) code |= 4; // below
34582     else if (phi > r) code |= 8; // above
34583     return code;
34584   }
34585
34586   return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$4, radius - pi$4]);
34587 };
34588
34589 var transform$1 = function(methods) {
34590   return {
34591     stream: transformer(methods)
34592   };
34593 };
34594
34595 function transformer(methods) {
34596   return function(stream) {
34597     var s = new TransformStream;
34598     for (var key in methods) s[key] = methods[key];
34599     s.stream = stream;
34600     return s;
34601   };
34602 }
34603
34604 function TransformStream() {}
34605
34606 TransformStream.prototype = {
34607   constructor: TransformStream,
34608   point: function(x, y) { this.stream.point(x, y); },
34609   sphere: function() { this.stream.sphere(); },
34610   lineStart: function() { this.stream.lineStart(); },
34611   lineEnd: function() { this.stream.lineEnd(); },
34612   polygonStart: function() { this.stream.polygonStart(); },
34613   polygonEnd: function() { this.stream.polygonEnd(); }
34614 };
34615
34616 function fitExtent(projection, extent, object) {
34617   var w = extent[1][0] - extent[0][0],
34618       h = extent[1][1] - extent[0][1],
34619       clip = projection.clipExtent && projection.clipExtent();
34620
34621   projection
34622       .scale(150)
34623       .translate([0, 0]);
34624
34625   if (clip != null) projection.clipExtent(null);
34626
34627   geoStream(object, projection.stream(boundsStream$1));
34628
34629   var b = boundsStream$1.result(),
34630       k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
34631       x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
34632       y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
34633
34634   if (clip != null) projection.clipExtent(clip);
34635
34636   return projection
34637       .scale(k * 150)
34638       .translate([x, y]);
34639 }
34640
34641 function fitSize(projection, size, object) {
34642   return fitExtent(projection, [[0, 0], size], object);
34643 }
34644
34645 var maxDepth = 16;
34646 var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance)
34647
34648 var resample = function(project, delta2) {
34649   return +delta2 ? resample$1(project, delta2) : resampleNone(project);
34650 };
34651
34652 function resampleNone(project) {
34653   return transformer({
34654     point: function(x, y) {
34655       x = project(x, y);
34656       this.stream.point(x[0], x[1]);
34657     }
34658   });
34659 }
34660
34661 function resample$1(project, delta2) {
34662
34663   function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
34664     var dx = x1 - x0,
34665         dy = y1 - y0,
34666         d2 = dx * dx + dy * dy;
34667     if (d2 > 4 * delta2 && depth--) {
34668       var a = a0 + a1,
34669           b = b0 + b1,
34670           c = c0 + c1,
34671           m = sqrt$1(a * a + b * b + c * c),
34672           phi2 = asin$1(c /= m),
34673           lambda2 = abs(abs(c) - 1) < epsilon$4 || abs(lambda0 - lambda1) < epsilon$4 ? (lambda0 + lambda1) / 2 : atan2(b, a),
34674           p = project(lambda2, phi2),
34675           x2 = p[0],
34676           y2 = p[1],
34677           dx2 = x2 - x0,
34678           dy2 = y2 - y0,
34679           dz = dy * dx2 - dx * dy2;
34680       if (dz * dz / d2 > delta2 // perpendicular projected distance
34681           || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
34682           || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
34683         resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
34684         stream.point(x2, y2);
34685         resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
34686       }
34687     }
34688   }
34689   return function(stream) {
34690     var lambda00, x00, y00, a00, b00, c00, // first point
34691         lambda0, x0, y0, a0, b0, c0; // previous point
34692
34693     var resampleStream = {
34694       point: point,
34695       lineStart: lineStart,
34696       lineEnd: lineEnd,
34697       polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
34698       polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
34699     };
34700
34701     function point(x, y) {
34702       x = project(x, y);
34703       stream.point(x[0], x[1]);
34704     }
34705
34706     function lineStart() {
34707       x0 = NaN;
34708       resampleStream.point = linePoint;
34709       stream.lineStart();
34710     }
34711
34712     function linePoint(lambda, phi) {
34713       var c = cartesian([lambda, phi]), p = project(lambda, phi);
34714       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);
34715       stream.point(x0, y0);
34716     }
34717
34718     function lineEnd() {
34719       resampleStream.point = point;
34720       stream.lineEnd();
34721     }
34722
34723     function ringStart() {
34724       lineStart();
34725       resampleStream.point = ringPoint;
34726       resampleStream.lineEnd = ringEnd;
34727     }
34728
34729     function ringPoint(lambda, phi) {
34730       linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
34731       resampleStream.point = linePoint;
34732     }
34733
34734     function ringEnd() {
34735       resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
34736       resampleStream.lineEnd = lineEnd;
34737       lineEnd();
34738     }
34739
34740     return resampleStream;
34741   };
34742 }
34743
34744 var transformRadians = transformer({
34745   point: function(x, y) {
34746     this.stream.point(x * radians, y * radians);
34747   }
34748 });
34749
34750 function projection(project) {
34751   return projectionMutator(function() { return project; })();
34752 }
34753
34754 function projectionMutator(projectAt) {
34755   var project,
34756       k = 150, // scale
34757       x = 480, y = 250, // translate
34758       dx, dy, lambda = 0, phi = 0, // center
34759       deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
34760       theta = null, preclip = clipAntimeridian, // clip angle
34761       x0 = null, y0, x1, y1, postclip = identity$7, // clip extent
34762       delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
34763       cache,
34764       cacheStream;
34765
34766   function projection(point) {
34767     point = projectRotate(point[0] * radians, point[1] * radians);
34768     return [point[0] * k + dx, dy - point[1] * k];
34769   }
34770
34771   function invert(point) {
34772     point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
34773     return point && [point[0] * degrees$1, point[1] * degrees$1];
34774   }
34775
34776   function projectTransform(x, y) {
34777     return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
34778   }
34779
34780   projection.stream = function(stream) {
34781     return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
34782   };
34783
34784   projection.clipAngle = function(_) {
34785     return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
34786   };
34787
34788   projection.clipExtent = function(_) {
34789     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]];
34790   };
34791
34792   projection.scale = function(_) {
34793     return arguments.length ? (k = +_, recenter()) : k;
34794   };
34795
34796   projection.translate = function(_) {
34797     return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
34798   };
34799
34800   projection.center = function(_) {
34801     return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
34802   };
34803
34804   projection.rotate = function(_) {
34805     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];
34806   };
34807
34808   projection.precision = function(_) {
34809     return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt$1(delta2);
34810   };
34811
34812   projection.fitExtent = function(extent, object) {
34813     return fitExtent(projection, extent, object);
34814   };
34815
34816   projection.fitSize = function(size, object) {
34817     return fitSize(projection, size, object);
34818   };
34819
34820   function recenter() {
34821     projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
34822     var center = project(lambda, phi);
34823     dx = x - center[0] * k;
34824     dy = y + center[1] * k;
34825     return reset();
34826   }
34827
34828   function reset() {
34829     cache = cacheStream = null;
34830     return projection;
34831   }
34832
34833   return function() {
34834     project = projectAt.apply(this, arguments);
34835     projection.invert = project.invert && invert;
34836     return recenter();
34837   };
34838 }
34839
34840 function conicProjection(projectAt) {
34841   var phi0 = 0,
34842       phi1 = pi$4 / 3,
34843       m = projectionMutator(projectAt),
34844       p = m(phi0, phi1);
34845
34846   p.parallels = function(_) {
34847     return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1];
34848   };
34849
34850   return p;
34851 }
34852
34853 function cylindricalEqualAreaRaw(phi0) {
34854   var cosPhi0 = cos$1(phi0);
34855
34856   function forward(lambda, phi) {
34857     return [lambda * cosPhi0, sin$1(phi) / cosPhi0];
34858   }
34859
34860   forward.invert = function(x, y) {
34861     return [x / cosPhi0, asin$1(y * cosPhi0)];
34862   };
34863
34864   return forward;
34865 }
34866
34867 function conicEqualAreaRaw(y0, y1) {
34868   var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2;
34869
34870   // Are the parallels symmetrical around the Equator?
34871   if (abs(n) < epsilon$4) return cylindricalEqualAreaRaw(y0);
34872
34873   var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt$1(c) / n;
34874
34875   function project(x, y) {
34876     var r = sqrt$1(c - 2 * n * sin$1(y)) / n;
34877     return [r * sin$1(x *= n), r0 - r * cos$1(x)];
34878   }
34879
34880   project.invert = function(x, y) {
34881     var r0y = r0 - y;
34882     return [atan2(x, abs(r0y)) / n * sign$1(r0y), asin$1((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
34883   };
34884
34885   return project;
34886 }
34887
34888 var conicEqualArea = function() {
34889   return conicProjection(conicEqualAreaRaw)
34890       .scale(155.424)
34891       .center([0, 33.6442]);
34892 };
34893
34894 var albers = function() {
34895   return conicEqualArea()
34896       .parallels([29.5, 45.5])
34897       .scale(1070)
34898       .translate([480, 250])
34899       .rotate([96, 0])
34900       .center([-0.6, 38.7]);
34901 };
34902
34903 // The projections must have mutually exclusive clip regions on the sphere,
34904 // as this will avoid emitting interleaving lines and polygons.
34905 function multiplex(streams) {
34906   var n = streams.length;
34907   return {
34908     point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
34909     sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
34910     lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
34911     lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
34912     polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
34913     polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
34914   };
34915 }
34916
34917 // A composite projection for the United States, configured by default for
34918 // 960×500. The projection also works quite well at 960×600 if you change the
34919 // scale to 1285 and adjust the translate accordingly. The set of standard
34920 // parallels for each region comes from USGS, which is published here:
34921 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
34922 var albersUsa = function() {
34923   var cache,
34924       cacheStream,
34925       lower48 = albers(), lower48Point,
34926       alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
34927       hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
34928       point, pointStream = {point: function(x, y) { point = [x, y]; }};
34929
34930   function albersUsa(coordinates) {
34931     var x = coordinates[0], y = coordinates[1];
34932     return point = null,
34933         (lower48Point.point(x, y), point)
34934         || (alaskaPoint.point(x, y), point)
34935         || (hawaiiPoint.point(x, y), point);
34936   }
34937
34938   albersUsa.invert = function(coordinates) {
34939     var k = lower48.scale(),
34940         t = lower48.translate(),
34941         x = (coordinates[0] - t[0]) / k,
34942         y = (coordinates[1] - t[1]) / k;
34943     return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
34944         : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
34945         : lower48).invert(coordinates);
34946   };
34947
34948   albersUsa.stream = function(stream) {
34949     return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
34950   };
34951
34952   albersUsa.precision = function(_) {
34953     if (!arguments.length) return lower48.precision();
34954     lower48.precision(_), alaska.precision(_), hawaii.precision(_);
34955     return reset();
34956   };
34957
34958   albersUsa.scale = function(_) {
34959     if (!arguments.length) return lower48.scale();
34960     lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
34961     return albersUsa.translate(lower48.translate());
34962   };
34963
34964   albersUsa.translate = function(_) {
34965     if (!arguments.length) return lower48.translate();
34966     var k = lower48.scale(), x = +_[0], y = +_[1];
34967
34968     lower48Point = lower48
34969         .translate(_)
34970         .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
34971         .stream(pointStream);
34972
34973     alaskaPoint = alaska
34974         .translate([x - 0.307 * k, y + 0.201 * k])
34975         .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]])
34976         .stream(pointStream);
34977
34978     hawaiiPoint = hawaii
34979         .translate([x - 0.205 * k, y + 0.212 * k])
34980         .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]])
34981         .stream(pointStream);
34982
34983     return reset();
34984   };
34985
34986   albersUsa.fitExtent = function(extent, object) {
34987     return fitExtent(albersUsa, extent, object);
34988   };
34989
34990   albersUsa.fitSize = function(size, object) {
34991     return fitSize(albersUsa, size, object);
34992   };
34993
34994   function reset() {
34995     cache = cacheStream = null;
34996     return albersUsa;
34997   }
34998
34999   return albersUsa.scale(1070);
35000 };
35001
35002 function azimuthalRaw(scale) {
35003   return function(x, y) {
35004     var cx = cos$1(x),
35005         cy = cos$1(y),
35006         k = scale(cx * cy);
35007     return [
35008       k * cy * sin$1(x),
35009       k * sin$1(y)
35010     ];
35011   }
35012 }
35013
35014 function azimuthalInvert(angle) {
35015   return function(x, y) {
35016     var z = sqrt$1(x * x + y * y),
35017         c = angle(z),
35018         sc = sin$1(c),
35019         cc = cos$1(c);
35020     return [
35021       atan2(x * sc, z * cc),
35022       asin$1(z && y * sc / z)
35023     ];
35024   }
35025 }
35026
35027 var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
35028   return sqrt$1(2 / (1 + cxcy));
35029 });
35030
35031 azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
35032   return 2 * asin$1(z / 2);
35033 });
35034
35035 var azimuthalEqualArea = function() {
35036   return projection(azimuthalEqualAreaRaw)
35037       .scale(124.75)
35038       .clipAngle(180 - 1e-3);
35039 };
35040
35041 var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
35042   return (c = acos(c)) && c / sin$1(c);
35043 });
35044
35045 azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
35046   return z;
35047 });
35048
35049 var azimuthalEquidistant = function() {
35050   return projection(azimuthalEquidistantRaw)
35051       .scale(79.4188)
35052       .clipAngle(180 - 1e-3);
35053 };
35054
35055 function mercatorRaw(lambda, phi) {
35056   return [lambda, log$1(tan((halfPi$3 + phi) / 2))];
35057 }
35058
35059 mercatorRaw.invert = function(x, y) {
35060   return [x, 2 * atan(exp(y)) - halfPi$3];
35061 };
35062
35063 var mercator = function() {
35064   return mercatorProjection(mercatorRaw)
35065       .scale(961 / tau$4);
35066 };
35067
35068 function mercatorProjection(project) {
35069   var m = projection(project),
35070       scale = m.scale,
35071       translate = m.translate,
35072       clipExtent = m.clipExtent,
35073       clipAuto;
35074
35075   m.scale = function(_) {
35076     return arguments.length ? (scale(_), clipAuto && m.clipExtent(null), m) : scale();
35077   };
35078
35079   m.translate = function(_) {
35080     return arguments.length ? (translate(_), clipAuto && m.clipExtent(null), m) : translate();
35081   };
35082
35083   m.clipExtent = function(_) {
35084     if (!arguments.length) return clipAuto ? null : clipExtent();
35085     if (clipAuto = _ == null) {
35086       var k = pi$4 * scale(),
35087           t = translate();
35088       _ = [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]];
35089     }
35090     clipExtent(_);
35091     return m;
35092   };
35093
35094   return m.clipExtent(null);
35095 }
35096
35097 function tany(y) {
35098   return tan((halfPi$3 + y) / 2);
35099 }
35100
35101 function conicConformalRaw(y0, y1) {
35102   var cy0 = cos$1(y0),
35103       n = y0 === y1 ? sin$1(y0) : log$1(cy0 / cos$1(y1)) / log$1(tany(y1) / tany(y0)),
35104       f = cy0 * pow$1(tany(y0), n) / n;
35105
35106   if (!n) return mercatorRaw;
35107
35108   function project(x, y) {
35109     if (f > 0) { if (y < -halfPi$3 + epsilon$4) y = -halfPi$3 + epsilon$4; }
35110     else { if (y > halfPi$3 - epsilon$4) y = halfPi$3 - epsilon$4; }
35111     var r = f / pow$1(tany(y), n);
35112     return [r * sin$1(n * x), f - r * cos$1(n * x)];
35113   }
35114
35115   project.invert = function(x, y) {
35116     var fy = f - y, r = sign$1(n) * sqrt$1(x * x + fy * fy);
35117     return [atan2(x, abs(fy)) / n * sign$1(fy), 2 * atan(pow$1(f / r, 1 / n)) - halfPi$3];
35118   };
35119
35120   return project;
35121 }
35122
35123 var conicConformal = function() {
35124   return conicProjection(conicConformalRaw)
35125       .scale(109.5)
35126       .parallels([30, 30]);
35127 };
35128
35129 function equirectangularRaw(lambda, phi) {
35130   return [lambda, phi];
35131 }
35132
35133 equirectangularRaw.invert = equirectangularRaw;
35134
35135 var equirectangular = function() {
35136   return projection(equirectangularRaw)
35137       .scale(152.63);
35138 };
35139
35140 function conicEquidistantRaw(y0, y1) {
35141   var cy0 = cos$1(y0),
35142       n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0),
35143       g = cy0 / n + y0;
35144
35145   if (abs(n) < epsilon$4) return equirectangularRaw;
35146
35147   function project(x, y) {
35148     var gy = g - y, nx = n * x;
35149     return [gy * sin$1(nx), g - gy * cos$1(nx)];
35150   }
35151
35152   project.invert = function(x, y) {
35153     var gy = g - y;
35154     return [atan2(x, abs(gy)) / n * sign$1(gy), g - sign$1(n) * sqrt$1(x * x + gy * gy)];
35155   };
35156
35157   return project;
35158 }
35159
35160 var conicEquidistant = function() {
35161   return conicProjection(conicEquidistantRaw)
35162       .scale(131.154)
35163       .center([0, 13.9389]);
35164 };
35165
35166 function gnomonicRaw(x, y) {
35167   var cy = cos$1(y), k = cos$1(x) * cy;
35168   return [cy * sin$1(x) / k, sin$1(y) / k];
35169 }
35170
35171 gnomonicRaw.invert = azimuthalInvert(atan);
35172
35173 var gnomonic = function() {
35174   return projection(gnomonicRaw)
35175       .scale(144.049)
35176       .clipAngle(60);
35177 };
35178
35179 function scaleTranslate(k, tx, ty) {
35180   return k === 1 && tx === 0 && ty === 0 ? identity$7 : transformer({
35181     point: function(x, y) {
35182       this.stream.point(x * k + tx, y * k + ty);
35183     }
35184   });
35185 }
35186
35187 var identity$8 = function() {
35188   var k = 1, tx = 0, ty = 0, transform = identity$7, // scale and translate
35189       x0 = null, y0, x1, y1, clip = identity$7, // clip extent
35190       cache,
35191       cacheStream,
35192       projection;
35193
35194   function reset() {
35195     cache = cacheStream = null;
35196     return projection;
35197   }
35198
35199   return projection = {
35200     stream: function(stream) {
35201       return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream));
35202     },
35203     clipExtent: function(_) {
35204       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]];
35205     },
35206     scale: function(_) {
35207       return arguments.length ? (transform = scaleTranslate(k = +_, tx, ty), reset()) : k;
35208     },
35209     translate: function(_) {
35210       return arguments.length ? (transform = scaleTranslate(k, tx = +_[0], ty = +_[1]), reset()) : [tx, ty];
35211     },
35212     fitExtent: function(extent, object) {
35213       return fitExtent(projection, extent, object);
35214     },
35215     fitSize: function(size, object) {
35216       return fitSize(projection, size, object);
35217     }
35218   };
35219 };
35220
35221 function orthographicRaw(x, y) {
35222   return [cos$1(y) * sin$1(x), sin$1(y)];
35223 }
35224
35225 orthographicRaw.invert = azimuthalInvert(asin$1);
35226
35227 var orthographic = function() {
35228   return projection(orthographicRaw)
35229       .scale(249.5)
35230       .clipAngle(90 + epsilon$4);
35231 };
35232
35233 function stereographicRaw(x, y) {
35234   var cy = cos$1(y), k = 1 + cos$1(x) * cy;
35235   return [cy * sin$1(x) / k, sin$1(y) / k];
35236 }
35237
35238 stereographicRaw.invert = azimuthalInvert(function(z) {
35239   return 2 * atan(z);
35240 });
35241
35242 var stereographic = function() {
35243   return projection(stereographicRaw)
35244       .scale(250)
35245       .clipAngle(142);
35246 };
35247
35248 function transverseMercatorRaw(lambda, phi) {
35249   return [log$1(tan((halfPi$3 + phi) / 2)), -lambda];
35250 }
35251
35252 transverseMercatorRaw.invert = function(x, y) {
35253   return [-y, 2 * atan(exp(x)) - halfPi$3];
35254 };
35255
35256 var transverseMercator = function() {
35257   var m = mercatorProjection(transverseMercatorRaw),
35258       center = m.center,
35259       rotate = m.rotate;
35260
35261   m.center = function(_) {
35262     return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
35263   };
35264
35265   m.rotate = function(_) {
35266     return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
35267   };
35268
35269   return rotate([0, 0, 90])
35270       .scale(159.155);
35271 };
35272
35273
35274
35275 var index$1 = Object.freeze({
35276         version: version,
35277         bisect: bisectRight,
35278         bisectRight: bisectRight,
35279         bisectLeft: bisectLeft,
35280         ascending: ascending,
35281         bisector: bisector,
35282         descending: descending,
35283         deviation: deviation,
35284         extent: extent,
35285         histogram: histogram,
35286         thresholdFreedmanDiaconis: freedmanDiaconis,
35287         thresholdScott: scott,
35288         thresholdSturges: sturges,
35289         max: max,
35290         mean: mean,
35291         median: median,
35292         merge: merge,
35293         min: min,
35294         pairs: pairs,
35295         permute: permute,
35296         quantile: threshold,
35297         range: range,
35298         scan: scan,
35299         shuffle: shuffle,
35300         sum: sum,
35301         ticks: ticks,
35302         tickStep: tickStep,
35303         transpose: transpose,
35304         variance: variance,
35305         zip: zip,
35306         entries: entries,
35307         keys: keys,
35308         values: values,
35309         map: map$1,
35310         set: set,
35311         nest: nest,
35312         randomUniform: uniform,
35313         randomNormal: normal,
35314         randomLogNormal: logNormal,
35315         randomBates: bates,
35316         randomIrwinHall: irwinHall,
35317         randomExponential: exponential,
35318         easeLinear: linear,
35319         easeQuad: quadInOut,
35320         easeQuadIn: quadIn,
35321         easeQuadOut: quadOut,
35322         easeQuadInOut: quadInOut,
35323         easeCubic: cubicInOut,
35324         easeCubicIn: cubicIn,
35325         easeCubicOut: cubicOut,
35326         easeCubicInOut: cubicInOut,
35327         easePoly: polyInOut,
35328         easePolyIn: polyIn,
35329         easePolyOut: polyOut,
35330         easePolyInOut: polyInOut,
35331         easeSin: sinInOut,
35332         easeSinIn: sinIn,
35333         easeSinOut: sinOut,
35334         easeSinInOut: sinInOut,
35335         easeExp: expInOut,
35336         easeExpIn: expIn,
35337         easeExpOut: expOut,
35338         easeExpInOut: expInOut,
35339         easeCircle: circleInOut,
35340         easeCircleIn: circleIn,
35341         easeCircleOut: circleOut,
35342         easeCircleInOut: circleInOut,
35343         easeBounce: bounceOut,
35344         easeBounceIn: bounceIn,
35345         easeBounceOut: bounceOut,
35346         easeBounceInOut: bounceInOut,
35347         easeBack: backInOut,
35348         easeBackIn: backIn,
35349         easeBackOut: backOut,
35350         easeBackInOut: backInOut,
35351         easeElastic: elasticOut,
35352         easeElasticIn: elasticIn,
35353         easeElasticOut: elasticOut,
35354         easeElasticInOut: elasticInOut,
35355         polygonArea: d3polygonArea,
35356         polygonCentroid: d3polygonCentroid,
35357         polygonHull: d3polygonHull,
35358         polygonContains: contains,
35359         polygonLength: length$1,
35360         path: path,
35361         quadtree: quadtree,
35362         queue: queue,
35363         arc: arc,
35364         area: area,
35365         line: line,
35366         pie: pie,
35367         radialArea: radialArea,
35368         radialLine: radialLine$1,
35369         symbol: symbol,
35370         symbols: symbols,
35371         symbolCircle: circle,
35372         symbolCross: cross$1,
35373         symbolDiamond: diamond,
35374         symbolSquare: square,
35375         symbolStar: star,
35376         symbolTriangle: triangle,
35377         symbolWye: wye,
35378         curveBasisClosed: basisClosed,
35379         curveBasisOpen: basisOpen,
35380         curveBasis: basis,
35381         curveBundle: bundle,
35382         curveCardinalClosed: cardinalClosed,
35383         curveCardinalOpen: cardinalOpen,
35384         curveCardinal: cardinal,
35385         curveCatmullRomClosed: catmullRomClosed,
35386         curveCatmullRomOpen: catmullRomOpen,
35387         curveCatmullRom: catmullRom,
35388         curveLinearClosed: linearClosed,
35389         curveLinear: curveLinear,
35390         curveMonotoneX: monotoneX,
35391         curveMonotoneY: monotoneY,
35392         curveNatural: natural,
35393         curveStep: step,
35394         curveStepAfter: stepAfter,
35395         curveStepBefore: stepBefore,
35396         stack: stack,
35397         stackOffsetExpand: expand,
35398         stackOffsetNone: none,
35399         stackOffsetSilhouette: silhouette,
35400         stackOffsetWiggle: wiggle,
35401         stackOrderAscending: ascending$1,
35402         stackOrderDescending: descending$2,
35403         stackOrderInsideOut: insideOut,
35404         stackOrderNone: none$1,
35405         stackOrderReverse: reverse,
35406         color: color,
35407         rgb: rgb,
35408         hsl: hsl,
35409         lab: lab,
35410         hcl: hcl,
35411         cubehelix: cubehelix,
35412         interpolate: interpolate,
35413         interpolateArray: array$1,
35414         interpolateDate: date,
35415         interpolateNumber: interpolateNumber,
35416         interpolateObject: object,
35417         interpolateRound: interpolateRound,
35418         interpolateString: interpolateString,
35419         interpolateTransformCss: interpolateTransformCss,
35420         interpolateTransformSvg: interpolateTransformSvg,
35421         interpolateZoom: interpolateZoom,
35422         interpolateRgb: interpolateRgb,
35423         interpolateRgbBasis: rgbBasis,
35424         interpolateRgbBasisClosed: rgbBasisClosed,
35425         interpolateHsl: hsl$2,
35426         interpolateHslLong: hslLong,
35427         interpolateLab: lab$1,
35428         interpolateHcl: hcl$2,
35429         interpolateHclLong: hclLong,
35430         interpolateCubehelix: cubehelix$2,
35431         interpolateCubehelixLong: cubehelixLong,
35432         interpolateBasis: basis$2,
35433         interpolateBasisClosed: basisClosed$1,
35434         quantize: quantize,
35435         dispatch: dispatch,
35436         dsvFormat: dsv,
35437         csvParse: csvParse,
35438         csvParseRows: csvParseRows,
35439         csvFormat: csvFormat,
35440         csvFormatRows: csvFormatRows,
35441         tsvParse: tsvParse,
35442         tsvParseRows: tsvParseRows,
35443         tsvFormat: tsvFormat,
35444         tsvFormatRows: tsvFormatRows,
35445         request: request,
35446         html: html,
35447         json: json,
35448         text: text,
35449         xml: xml,
35450         csv: csv$1,
35451         tsv: tsv$1,
35452         now: now,
35453         timer: timer,
35454         timerFlush: timerFlush,
35455         timeout: timeout$1,
35456         interval: interval$1,
35457         timeInterval: newInterval,
35458         timeMillisecond: millisecond,
35459         timeMilliseconds: milliseconds,
35460         timeSecond: second,
35461         timeSeconds: seconds,
35462         timeMinute: minute,
35463         timeMinutes: minutes,
35464         timeHour: hour,
35465         timeHours: hours,
35466         timeDay: day,
35467         timeDays: days,
35468         timeWeek: sunday,
35469         timeWeeks: sundays,
35470         timeSunday: sunday,
35471         timeSundays: sundays,
35472         timeMonday: monday,
35473         timeMondays: mondays,
35474         timeTuesday: tuesday,
35475         timeTuesdays: tuesdays,
35476         timeWednesday: wednesday,
35477         timeWednesdays: wednesdays,
35478         timeThursday: thursday,
35479         timeThursdays: thursdays,
35480         timeFriday: friday,
35481         timeFridays: fridays,
35482         timeSaturday: saturday,
35483         timeSaturdays: saturdays,
35484         timeMonth: month,
35485         timeMonths: months,
35486         timeYear: year,
35487         timeYears: years,
35488         utcMillisecond: millisecond,
35489         utcMilliseconds: milliseconds,
35490         utcSecond: second,
35491         utcSeconds: seconds,
35492         utcMinute: utcMinute,
35493         utcMinutes: utcMinutes,
35494         utcHour: utcHour,
35495         utcHours: utcHours,
35496         utcDay: utcDay,
35497         utcDays: utcDays,
35498         utcWeek: utcSunday,
35499         utcWeeks: utcSundays,
35500         utcSunday: utcSunday,
35501         utcSundays: utcSundays,
35502         utcMonday: utcMonday,
35503         utcMondays: utcMondays,
35504         utcTuesday: utcTuesday,
35505         utcTuesdays: utcTuesdays,
35506         utcWednesday: utcWednesday,
35507         utcWednesdays: utcWednesdays,
35508         utcThursday: utcThursday,
35509         utcThursdays: utcThursdays,
35510         utcFriday: utcFriday,
35511         utcFridays: utcFridays,
35512         utcSaturday: utcSaturday,
35513         utcSaturdays: utcSaturdays,
35514         utcMonth: utcMonth,
35515         utcMonths: utcMonths,
35516         utcYear: utcYear,
35517         utcYears: utcYears,
35518         get format () { return format; },
35519         get formatPrefix () { return formatPrefix; },
35520         formatLocale: formatLocale,
35521         formatDefaultLocale: defaultLocale,
35522         formatSpecifier: formatSpecifier,
35523         precisionFixed: precisionFixed,
35524         precisionPrefix: precisionPrefix,
35525         precisionRound: precisionRound,
35526         get timeFormat () { return timeFormat; },
35527         get timeParse () { return timeParse; },
35528         get utcFormat () { return utcFormat; },
35529         get utcParse () { return utcParse; },
35530         isoFormat: formatIso,
35531         isoParse: parseIso,
35532         timeFormatLocale: formatLocale$1,
35533         timeFormatDefaultLocale: defaultLocale$1,
35534         scaleBand: band,
35535         scalePoint: point$4,
35536         scaleIdentity: identity$4,
35537         scaleLinear: linear$2,
35538         scaleLog: log,
35539         scaleOrdinal: ordinal,
35540         scaleImplicit: implicit,
35541         scalePow: pow,
35542         scaleSqrt: sqrt,
35543         scaleQuantile: quantile$$1,
35544         scaleQuantize: quantize$1,
35545         scaleThreshold: threshold$1,
35546         scaleTime: time,
35547         scaleUtc: utcTime,
35548         schemeCategory10: category10,
35549         schemeCategory20b: category20b,
35550         schemeCategory20c: category20c,
35551         schemeCategory20: category20,
35552         scaleSequential: sequential,
35553         interpolateCubehelixDefault: cubehelix$3,
35554         interpolateRainbow: rainbow$1,
35555         interpolateWarm: warm,
35556         interpolateCool: cool,
35557         interpolateViridis: viridis,
35558         interpolateMagma: magma,
35559         interpolateInferno: inferno,
35560         interpolatePlasma: plasma,
35561         creator: creator,
35562         customEvent: customEvent,
35563         get event () { return event; },
35564         local: local,
35565         matcher: matcher$1,
35566         mouse: mouse,
35567         namespace: namespace,
35568         namespaces: namespaces,
35569         select: select,
35570         selectAll: selectAll,
35571         selection: selection,
35572         selector: selector,
35573         selectorAll: selectorAll,
35574         touch: touch,
35575         touches: touches,
35576         window: window$1,
35577         active: active,
35578         interrupt: interrupt,
35579         transition: transition,
35580         axisTop: axisTop,
35581         axisRight: axisRight,
35582         axisBottom: axisBottom,
35583         axisLeft: axisLeft,
35584         cluster: cluster,
35585         hierarchy: hierarchy,
35586         pack: index$2,
35587         packSiblings: siblings,
35588         packEnclose: enclose,
35589         partition: partition,
35590         stratify: stratify,
35591         tree: tree,
35592         treemap: index$3,
35593         treemapBinary: binary,
35594         treemapDice: treemapDice,
35595         treemapSlice: treemapSlice,
35596         treemapSliceDice: sliceDice,
35597         treemapSquarify: squarify,
35598         treemapResquarify: resquarify,
35599         forceCenter: center$1,
35600         forceCollide: collide,
35601         forceLink: link,
35602         forceManyBody: manyBody,
35603         forceSimulation: simulation,
35604         forceX: x$3,
35605         forceY: y$3,
35606         drag: drag,
35607         dragDisable: dragDisable,
35608         dragEnable: yesdrag,
35609         voronoi: voronoi,
35610         zoom: zoom,
35611         zoomIdentity: identity$6,
35612         zoomTransform: transform,
35613         brush: brush,
35614         brushX: brushX,
35615         brushY: brushY,
35616         brushSelection: brushSelection,
35617         chord: chord,
35618         ribbon: ribbon,
35619         geoAlbers: albers,
35620         geoAlbersUsa: albersUsa,
35621         geoArea: area$1,
35622         geoAzimuthalEqualArea: azimuthalEqualArea,
35623         geoAzimuthalEqualAreaRaw: azimuthalEqualAreaRaw,
35624         geoAzimuthalEquidistant: azimuthalEquidistant,
35625         geoAzimuthalEquidistantRaw: azimuthalEquidistantRaw,
35626         geoBounds: bounds,
35627         geoCentroid: d3GeoCentroid,
35628         geoCircle: circle$1,
35629         geoClipExtent: extent$1,
35630         geoConicConformal: conicConformal,
35631         geoConicConformalRaw: conicConformalRaw,
35632         geoConicEqualArea: conicEqualArea,
35633         geoConicEqualAreaRaw: conicEqualAreaRaw,
35634         geoConicEquidistant: conicEquidistant,
35635         geoConicEquidistantRaw: conicEquidistantRaw,
35636         geoDistance: distance,
35637         geoEquirectangular: equirectangular,
35638         geoEquirectangularRaw: equirectangularRaw,
35639         geoGnomonic: gnomonic,
35640         geoGnomonicRaw: gnomonicRaw,
35641         geoGraticule: graticule,
35642         geoGraticule10: graticule10,
35643         geoIdentity: identity$8,
35644         geoInterpolate: interpolate$2,
35645         geoLength: d3GeoLength,
35646         geoMercator: mercator,
35647         geoMercatorRaw: mercatorRaw,
35648         geoOrthographic: orthographic,
35649         geoOrthographicRaw: orthographicRaw,
35650         geoPath: index$5,
35651         geoProjection: projection,
35652         geoProjectionMutator: projectionMutator,
35653         geoRotation: rotation,
35654         geoStereographic: stereographic,
35655         geoStereographicRaw: stereographicRaw,
35656         geoStream: geoStream,
35657         geoTransform: transform$1,
35658         geoTransverseMercator: transverseMercator,
35659         geoTransverseMercatorRaw: transverseMercatorRaw
35660 });
35661
35662 /*
35663     Bypasses features of D3's default projection stream pipeline that are unnecessary:
35664     * Antimeridian clipping
35665     * Spherical rotation
35666     * Resampling
35667 */
35668 function geoRawMercator() {
35669     var project = mercatorRaw,
35670         k = 512 / Math.PI, // scale
35671         x = 0, y = 0, // translate
35672         clipExtent = [[0, 0], [0, 0]];
35673
35674
35675     function projection(point) {
35676         point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
35677         return [point[0] * k + x, y - point[1] * k];
35678     }
35679
35680
35681     projection.invert = function(point) {
35682         point = project.invert((point[0] - x) / k, (y - point[1]) / k);
35683         return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
35684     };
35685
35686
35687     projection.scale = function(_) {
35688         if (!arguments.length) return k;
35689         k = +_;
35690         return projection;
35691     };
35692
35693
35694     projection.translate = function(_) {
35695         if (!arguments.length) return [x, y];
35696         x = +_[0];
35697         y = +_[1];
35698         return projection;
35699     };
35700
35701
35702     projection.clipExtent = function(_) {
35703         if (!arguments.length) return clipExtent;
35704         clipExtent = _;
35705         return projection;
35706     };
35707
35708
35709     projection.transform = function(_) {
35710         if (!arguments.length) return identity$6.translate(x, y).scale(k);
35711         x = +_.x;
35712         y = +_.y;
35713         k = +_.k;
35714         return projection;
35715     };
35716
35717
35718     projection.stream = transform$1({
35719         point: function(x, y) {
35720             x = projection([x, y]);
35721             this.stream.point(x[0], x[1]);
35722         }
35723     }).stream;
35724
35725
35726     return projection;
35727 }
35728
35729 function geoRoundCoords(c) {
35730     return [Math.floor(c[0]), Math.floor(c[1])];
35731 }
35732
35733
35734 function geoInterp(p1, p2, t) {
35735     return [p1[0] + (p2[0] - p1[0]) * t,
35736             p1[1] + (p2[1] - p1[1]) * t];
35737 }
35738
35739
35740 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
35741 // Returns a positive value, if OAB makes a counter-clockwise turn,
35742 // negative for clockwise turn, and zero if the points are collinear.
35743 function geoCross(o, a, b) {
35744     return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
35745 }
35746
35747
35748 // http://jsperf.com/id-dist-optimization
35749 function geoEuclideanDistance(a, b) {
35750     var x = a[0] - b[0], y = a[1] - b[1];
35751     return Math.sqrt((x * x) + (y * y));
35752 }
35753
35754
35755 // using WGS84 polar radius (6356752.314245179 m)
35756 // const = 2 * PI * r / 360
35757 function geoLatToMeters(dLat) {
35758     return dLat * 110946.257617;
35759 }
35760
35761
35762 // using WGS84 equatorial radius (6378137.0 m)
35763 // const = 2 * PI * r / 360
35764 function geoLonToMeters(dLon, atLat) {
35765     return Math.abs(atLat) >= 90 ? 0 :
35766         dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
35767 }
35768
35769
35770 // using WGS84 polar radius (6356752.314245179 m)
35771 // const = 2 * PI * r / 360
35772 function geoMetersToLat(m) {
35773     return m / 110946.257617;
35774 }
35775
35776
35777 // using WGS84 equatorial radius (6378137.0 m)
35778 // const = 2 * PI * r / 360
35779 function geoMetersToLon(m, atLat) {
35780     return Math.abs(atLat) >= 90 ? 0 :
35781         m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
35782 }
35783
35784
35785 function geoOffsetToMeters(offset) {
35786     var equatRadius = 6356752.314245179,
35787         polarRadius = 6378137.0,
35788         tileSize = 256;
35789
35790     return [
35791         offset[0] * 2 * Math.PI * equatRadius / tileSize,
35792         -offset[1] * 2 * Math.PI * polarRadius / tileSize
35793     ];
35794 }
35795
35796
35797 function geoMetersToOffset(meters) {
35798     var equatRadius = 6356752.314245179,
35799         polarRadius = 6378137.0,
35800         tileSize = 256;
35801
35802     return [
35803         meters[0] * tileSize / (2 * Math.PI * equatRadius),
35804         -meters[1] * tileSize / (2 * Math.PI * polarRadius)
35805     ];
35806 }
35807
35808
35809 // Equirectangular approximation of spherical distances on Earth
35810 function geoSphericalDistance(a, b) {
35811     var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
35812         y = geoLatToMeters(a[1] - b[1]);
35813     return Math.sqrt((x * x) + (y * y));
35814 }
35815
35816
35817 function geoEdgeEqual(a, b) {
35818     return (a[0] === b[0] && a[1] === b[1]) ||
35819         (a[0] === b[1] && a[1] === b[0]);
35820 }
35821
35822
35823 // Return the counterclockwise angle in the range (-pi, pi)
35824 // between the positive X axis and the line intersecting a and b.
35825 function geoAngle(a, b, projection) {
35826     a = projection(a.loc);
35827     b = projection(b.loc);
35828     return Math.atan2(b[1] - a[1], b[0] - a[0]);
35829 }
35830
35831
35832 // Choose the edge with the minimal distance from `point` to its orthogonal
35833 // projection onto that edge, if such a projection exists, or the distance to
35834 // the closest vertex on that edge. Returns an object with the `index` of the
35835 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
35836 function geoChooseEdge(nodes, point, projection) {
35837     var dist = geoEuclideanDistance,
35838         points = nodes.map(function(n) { return projection(n.loc); }),
35839         min = Infinity,
35840         idx, loc;
35841
35842     function dot(p, q) {
35843         return p[0] * q[0] + p[1] * q[1];
35844     }
35845
35846     for (var i = 0; i < points.length - 1; i++) {
35847         var o = points[i],
35848             s = [points[i + 1][0] - o[0],
35849                  points[i + 1][1] - o[1]],
35850             v = [point[0] - o[0],
35851                  point[1] - o[1]],
35852             proj = dot(v, s) / dot(s, s),
35853             p;
35854
35855         if (proj < 0) {
35856             p = o;
35857         } else if (proj > 1) {
35858             p = points[i + 1];
35859         } else {
35860             p = [o[0] + proj * s[0], o[1] + proj * s[1]];
35861         }
35862
35863         var d = dist(p, point);
35864         if (d < min) {
35865             min = d;
35866             idx = i + 1;
35867             loc = projection.invert(p);
35868         }
35869     }
35870
35871     return {
35872         index: idx,
35873         distance: min,
35874         loc: loc
35875     };
35876 }
35877
35878
35879 // Return the intersection point of 2 line segments.
35880 // From https://github.com/pgkelley4/line-segments-intersect
35881 // This uses the vector cross product approach described below:
35882 //  http://stackoverflow.com/a/565282/786339
35883 function geoLineIntersection(a, b) {
35884     function subtractPoints(point1, point2) {
35885         return [point1[0] - point2[0], point1[1] - point2[1]];
35886     }
35887     function crossProduct(point1, point2) {
35888         return point1[0] * point2[1] - point1[1] * point2[0];
35889     }
35890
35891     var p = [a[0][0], a[0][1]],
35892         p2 = [a[1][0], a[1][1]],
35893         q = [b[0][0], b[0][1]],
35894         q2 = [b[1][0], b[1][1]],
35895         r = subtractPoints(p2, p),
35896         s = subtractPoints(q2, q),
35897         uNumerator = crossProduct(subtractPoints(q, p), r),
35898         denominator = crossProduct(r, s);
35899
35900     if (uNumerator && denominator) {
35901         var u = uNumerator / denominator,
35902             t = crossProduct(subtractPoints(q, p), s) / denominator;
35903
35904         if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
35905             return geoInterp(p, p2, t);
35906         }
35907     }
35908
35909     return null;
35910 }
35911
35912
35913 function geoPathIntersections(path1, path2) {
35914     var intersections = [];
35915     for (var i = 0; i < path1.length - 1; i++) {
35916         for (var j = 0; j < path2.length - 1; j++) {
35917             var a = [ path1[i], path1[i+1] ],
35918                 b = [ path2[j], path2[j+1] ],
35919                 hit = geoLineIntersection(a, b);
35920             if (hit) intersections.push(hit);
35921         }
35922     }
35923     return intersections;
35924 }
35925
35926
35927 // Return whether point is contained in polygon.
35928 //
35929 // `point` should be a 2-item array of coordinates.
35930 // `polygon` should be an array of 2-item arrays of coordinates.
35931 //
35932 // From https://github.com/substack/point-in-polygon.
35933 // ray-casting algorithm based on
35934 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
35935 //
35936 function geoPointInPolygon(point, polygon) {
35937     var x = point[0],
35938         y = point[1],
35939         inside = false;
35940
35941     for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
35942         var xi = polygon[i][0], yi = polygon[i][1];
35943         var xj = polygon[j][0], yj = polygon[j][1];
35944
35945         var intersect = ((yi > y) !== (yj > y)) &&
35946             (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
35947         if (intersect) inside = !inside;
35948     }
35949
35950     return inside;
35951 }
35952
35953
35954 function geoPolygonContainsPolygon(outer, inner) {
35955     return lodash.every(inner, function(point) {
35956         return geoPointInPolygon(point, outer);
35957     });
35958 }
35959
35960
35961 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
35962     function testSegments(outer, inner) {
35963         for (var i = 0; i < outer.length - 1; i++) {
35964             for (var j = 0; j < inner.length - 1; j++) {
35965                 var a = [ outer[i], outer[i+1] ],
35966                     b = [ inner[j], inner[j+1] ];
35967                 if (geoLineIntersection(a, b)) return true;
35968             }
35969         }
35970         return false;
35971     }
35972
35973     function testPoints(outer, inner) {
35974         return lodash.some(inner, function(point) {
35975             return geoPointInPolygon(point, outer);
35976         });
35977     }
35978
35979    return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
35980 }
35981
35982
35983 function geoPathLength(path) {
35984     var length = 0;
35985     for (var i = 0; i < path.length - 1; i++) {
35986         length += geoEuclideanDistance(path[i], path[i + 1]);
35987     }
35988     return length;
35989 }
35990
35991 function osmNode() {
35992     if (!(this instanceof osmNode)) {
35993         return (new osmNode()).initialize(arguments);
35994     } else if (arguments.length) {
35995         this.initialize(arguments);
35996     }
35997 }
35998
35999 osmEntity$$1.node = osmNode;
36000
36001 osmNode.prototype = Object.create(osmEntity$$1.prototype);
36002
36003 lodash.extend(osmNode.prototype, {
36004
36005     type: 'node',
36006
36007
36008     extent: function() {
36009         return new geoExtent$$1(this.loc);
36010     },
36011
36012
36013     geometry: function(graph) {
36014         return graph.transient(this, 'geometry', function() {
36015             return graph.isPoi(this) ? 'point' : 'vertex';
36016         });
36017     },
36018
36019
36020     move: function(loc) {
36021         return this.update({loc: loc});
36022     },
36023
36024
36025     isIntersection: function(resolver) {
36026         return resolver.transient(this, 'isIntersection', function() {
36027             return resolver.parentWays(this).filter(function(parent) {
36028                 return (parent.tags.highway ||
36029                     parent.tags.waterway ||
36030                     parent.tags.railway ||
36031                     parent.tags.aeroway) &&
36032                     parent.geometry(resolver) === 'line';
36033             }).length > 1;
36034         });
36035     },
36036
36037
36038     isHighwayIntersection: function(resolver) {
36039         return resolver.transient(this, 'isHighwayIntersection', function() {
36040             return resolver.parentWays(this).filter(function(parent) {
36041                 return parent.tags.highway && parent.geometry(resolver) === 'line';
36042             }).length > 1;
36043         });
36044     },
36045
36046
36047     isOnAddressLine: function(resolver) {
36048         return resolver.transient(this, 'isOnAddressLine', function() {
36049             return resolver.parentWays(this).filter(function(parent) {
36050                 return parent.tags.hasOwnProperty('addr:interpolation') &&
36051                     parent.geometry(resolver) === 'line';
36052             }).length > 0;
36053         });
36054     },
36055
36056
36057     asJXON: function(changeset_id) {
36058         var r = {
36059             node: {
36060                 '@id': this.osmId(),
36061                 '@lon': this.loc[0],
36062                 '@lat': this.loc[1],
36063                 '@version': (this.version || 0),
36064                 tag: lodash.map(this.tags, function(v, k) {
36065                     return { keyAttributes: { k: k, v: v } };
36066                 })
36067             }
36068         };
36069         if (changeset_id) r.node['@changeset'] = changeset_id;
36070         return r;
36071     },
36072
36073
36074     asGeoJSON: function() {
36075         return {
36076             type: 'Point',
36077             coordinates: this.loc
36078         };
36079     }
36080 });
36081
36082 /*
36083   Order the nodes of a way in reverse order and reverse any direction dependent tags
36084   other than `oneway`. (We assume that correcting a backwards oneway is the primary
36085   reason for reversing a way.)
36086
36087   The following transforms are performed:
36088
36089     Keys:
36090           *:right=* ⟺ *:left=*
36091         *:forward=* ⟺ *:backward=*
36092        direction=up ⟺ direction=down
36093          incline=up ⟺ incline=down
36094             *=right ⟺ *=left
36095
36096     Relation members:
36097        role=forward ⟺ role=backward
36098          role=north ⟺ role=south
36099           role=east ⟺ role=west
36100
36101    In addition, numeric-valued `incline` tags are negated.
36102
36103    The JOSM implementation was used as a guide, but transformations that were of unclear benefit
36104    or adjusted tags that don't seem to be used in practice were omitted.
36105
36106    Also, each node on the way is examined for its own tags and the following transformations are performed
36107    in order to ensure associated nodes (eg a Stop Sign) is also reversed
36108
36109     Node Keys:
36110         direction=forward ⟺ direction=backward
36111         direction=left ⟺ direction=right
36112         *:forward=* ⟺ *:backward=*
36113         *:left=* ⟺ *:right=*
36114
36115    References:
36116       http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
36117       http://wiki.openstreetmap.org/wiki/Key:direction#Steps
36118       http://wiki.openstreetmap.org/wiki/Key:incline
36119       http://wiki.openstreetmap.org/wiki/Route#Members
36120       http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
36121       http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
36122       http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
36123  */
36124 function actionReverse(wayId, options) {
36125     var replacements = [
36126             [/:right$/, ':left'], [/:left$/, ':right'],
36127             [/:forward$/, ':backward'], [/:backward$/, ':forward']
36128         ],
36129         numeric = /^([+\-]?)(?=[\d.])/,
36130         roleReversals = {
36131             forward: 'backward',
36132             backward: 'forward',
36133             north: 'south',
36134             south: 'north',
36135             east: 'west',
36136             west: 'east'
36137         };
36138
36139
36140     function reverseKey(key) {
36141         for (var i = 0; i < replacements.length; ++i) {
36142             var replacement = replacements[i];
36143             if (replacement[0].test(key)) {
36144                 return key.replace(replacement[0], replacement[1]);
36145             }
36146         }
36147         return key;
36148     }
36149
36150
36151     function reverseValue(key, value) {
36152         if (key === 'incline' && numeric.test(value)) {
36153             return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
36154         } else if (key === 'incline' || key === 'direction') {
36155             return {up: 'down', down: 'up'}[value] || value;
36156         } else if (options && options.reverseOneway && key === 'oneway') {
36157             return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
36158         } else {
36159             return {left: 'right', right: 'left'}[value] || value;
36160         }
36161     }
36162
36163
36164     function reverseDirectionTags(node) {
36165         // Update the direction based tags as appropriate then return an updated node
36166         return node.update({tags: lodash.transform(node.tags, function(acc, tagValue, tagKey) {
36167             // See if this is a direction tag and reverse (or use existing value if not recognised)
36168             if (tagKey === 'direction') {
36169                 acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
36170             } else {
36171                 // Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
36172                 // This will pass through other tags unchanged
36173                 acc[reverseKey(tagKey)] = tagValue;
36174             }
36175             return acc;
36176         }, {})});
36177     }
36178
36179
36180     function reverseTagsOnNodes(graph, nodeIds) {
36181         // Reverse the direction of appropriate tags attached to the nodes (#3076)
36182         return lodash(nodeIds)
36183             // Get each node from the graph
36184             .map(function(nodeId) { return graph.entity(nodeId);})
36185             // Check tags on the node, if there aren't any, we can skip
36186             .filter(function(existingNode) { return existingNode.tags !== undefined;})
36187             // Get a new version of each node with the appropriate tags reversed
36188             .map(function(existingNode) { return reverseDirectionTags(existingNode);})
36189             // Chain together consecutive updates to the graph for each updated node and return
36190             .reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
36191     }
36192
36193
36194     return function(graph) {
36195         var way = graph.entity(wayId),
36196             nodes = way.nodes.slice().reverse(),
36197             tags = {}, key, role;
36198
36199         for (key in way.tags) {
36200             tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
36201         }
36202
36203         graph.parentRelations(way).forEach(function(relation) {
36204             relation.members.forEach(function(member, index) {
36205                 if (member.id === way.id && (role = roleReversals[member.role])) {
36206                     relation = relation.updateMember({role: role}, index);
36207                     graph = graph.replace(relation);
36208                 }
36209             });
36210         });
36211
36212         // Reverse any associated directions on nodes on the way and then replace
36213         // the way itself with the reversed node ids and updated way tags
36214         return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
36215     };
36216 }
36217
36218 // For fixing up rendering of multipolygons with tags on the outer member.
36219 // https://github.com/openstreetmap/iD/issues/613
36220 function osmIsSimpleMultipolygonOuterMember(entity, graph) {
36221     if (entity.type !== 'way')
36222         return false;
36223
36224     var parents = graph.parentRelations(entity);
36225     if (parents.length !== 1)
36226         return false;
36227
36228     var parent = parents[0];
36229     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36230         return false;
36231
36232     var members = parent.members, member;
36233     for (var i = 0; i < members.length; i++) {
36234         member = members[i];
36235         if (member.id === entity.id && member.role && member.role !== 'outer')
36236             return false; // Not outer member
36237         if (member.id !== entity.id && (!member.role || member.role === 'outer'))
36238             return false; // Not a simple multipolygon
36239     }
36240
36241     return parent;
36242 }
36243
36244
36245 function osmSimpleMultipolygonOuterMember(entity, graph) {
36246     if (entity.type !== 'way')
36247         return false;
36248
36249     var parents = graph.parentRelations(entity);
36250     if (parents.length !== 1)
36251         return false;
36252
36253     var parent = parents[0];
36254     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36255         return false;
36256
36257     var members = parent.members, member, outerMember;
36258     for (var i = 0; i < members.length; i++) {
36259         member = members[i];
36260         if (!member.role || member.role === 'outer') {
36261             if (outerMember)
36262                 return false; // Not a simple multipolygon
36263             outerMember = member;
36264         }
36265     }
36266
36267     return outerMember && graph.hasEntity(outerMember.id);
36268 }
36269
36270
36271 // Join `array` into sequences of connecting ways.
36272 //
36273 // Segments which share identical start/end nodes will, as much as possible,
36274 // be connected with each other.
36275 //
36276 // The return value is a nested array. Each constituent array contains elements
36277 // of `array` which have been determined to connect. Each consitituent array
36278 // also has a `nodes` property whose value is an ordered array of member nodes,
36279 // with appropriate order reversal and start/end coordinate de-duplication.
36280 //
36281 // Members of `array` must have, at minimum, `type` and `id` properties.
36282 // Thus either an array of `osmWay`s or a relation member array may be
36283 // used.
36284 //
36285 // If an member has a `tags` property, its tags will be reversed via
36286 // `actionReverse` in the output.
36287 //
36288 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
36289 // false) and non-way members are ignored.
36290 //
36291 function osmJoinWays(array, graph) {
36292     var joined = [], member, current, nodes, first, last, i, how, what;
36293
36294     array = array.filter(function(member) {
36295         return member.type === 'way' && graph.hasEntity(member.id);
36296     });
36297
36298     function resolve(member) {
36299         return graph.childNodes(graph.entity(member.id));
36300     }
36301
36302     function reverse(member) {
36303         return member.tags ? actionReverse(member.id, { reverseOneway: true })(graph).entity(member.id) : member;
36304     }
36305
36306     while (array.length) {
36307         member = array.shift();
36308         current = [member];
36309         current.nodes = nodes = resolve(member).slice();
36310         joined.push(current);
36311
36312         while (array.length && lodash.first(nodes) !== lodash.last(nodes)) {
36313             first = lodash.first(nodes);
36314             last  = lodash.last(nodes);
36315
36316             for (i = 0; i < array.length; i++) {
36317                 member = array[i];
36318                 what = resolve(member);
36319
36320                 if (last === lodash.first(what)) {
36321                     how  = nodes.push;
36322                     what = what.slice(1);
36323                     break;
36324                 } else if (last === lodash.last(what)) {
36325                     how  = nodes.push;
36326                     what = what.slice(0, -1).reverse();
36327                     member = reverse(member);
36328                     break;
36329                 } else if (first === lodash.last(what)) {
36330                     how  = nodes.unshift;
36331                     what = what.slice(0, -1);
36332                     break;
36333                 } else if (first === lodash.first(what)) {
36334                     how  = nodes.unshift;
36335                     what = what.slice(1).reverse();
36336                     member = reverse(member);
36337                     break;
36338                 } else {
36339                     what = how = null;
36340                 }
36341             }
36342
36343             if (!what)
36344                 break; // No more joinable ways.
36345
36346             how.apply(current, [member]);
36347             how.apply(nodes, what);
36348
36349             array.splice(i, 1);
36350         }
36351     }
36352
36353     return joined;
36354 }
36355
36356 function osmRelation() {
36357     if (!(this instanceof osmRelation)) {
36358         return (new osmRelation()).initialize(arguments);
36359     } else if (arguments.length) {
36360         this.initialize(arguments);
36361     }
36362 }
36363
36364
36365 osmEntity$$1.relation = osmRelation;
36366
36367 osmRelation.prototype = Object.create(osmEntity$$1.prototype);
36368
36369
36370 osmRelation.creationOrder = function(a, b) {
36371     var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10);
36372     var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10);
36373
36374     if (aId < 0 || bId < 0) return aId - bId;
36375     return bId - aId;
36376 };
36377
36378
36379 lodash.extend(osmRelation.prototype, {
36380     type: 'relation',
36381     members: [],
36382
36383
36384     copy: function(resolver, copies) {
36385         if (copies[this.id])
36386             return copies[this.id];
36387
36388         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
36389
36390         var members = this.members.map(function(member) {
36391             return lodash.extend({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
36392         });
36393
36394         copy = copy.update({members: members});
36395         copies[this.id] = copy;
36396
36397         return copy;
36398     },
36399
36400
36401     extent: function(resolver, memo) {
36402         return resolver.transient(this, 'extent', function() {
36403             if (memo && memo[this.id]) return geoExtent$$1();
36404             memo = memo || {};
36405             memo[this.id] = true;
36406
36407             var extent$$1 = geoExtent$$1();
36408             for (var i = 0; i < this.members.length; i++) {
36409                 var member = resolver.hasEntity(this.members[i].id);
36410                 if (member) {
36411                     extent$$1._extend(member.extent(resolver, memo));
36412                 }
36413             }
36414             return extent$$1;
36415         });
36416     },
36417
36418
36419     geometry: function(graph) {
36420         return graph.transient(this, 'geometry', function() {
36421             return this.isMultipolygon() ? 'area' : 'relation';
36422         });
36423     },
36424
36425
36426     isDegenerate: function() {
36427         return this.members.length === 0;
36428     },
36429
36430
36431     // Return an array of members, each extended with an 'index' property whose value
36432     // is the member index.
36433     indexedMembers: function() {
36434         var result = new Array(this.members.length);
36435         for (var i = 0; i < this.members.length; i++) {
36436             result[i] = lodash.extend({}, this.members[i], {index: i});
36437         }
36438         return result;
36439     },
36440
36441
36442     // Return the first member with the given role. A copy of the member object
36443     // is returned, extended with an 'index' property whose value is the member index.
36444     memberByRole: function(role) {
36445         for (var i = 0; i < this.members.length; i++) {
36446             if (this.members[i].role === role) {
36447                 return lodash.extend({}, this.members[i], {index: i});
36448             }
36449         }
36450     },
36451
36452
36453     // Return the first member with the given id. A copy of the member object
36454     // is returned, extended with an 'index' property whose value is the member index.
36455     memberById: function(id) {
36456         for (var i = 0; i < this.members.length; i++) {
36457             if (this.members[i].id === id) {
36458                 return lodash.extend({}, this.members[i], {index: i});
36459             }
36460         }
36461     },
36462
36463
36464     // Return the first member with the given id and role. A copy of the member object
36465     // is returned, extended with an 'index' property whose value is the member index.
36466     memberByIdAndRole: function(id, role) {
36467         for (var i = 0; i < this.members.length; i++) {
36468             if (this.members[i].id === id && this.members[i].role === role) {
36469                 return lodash.extend({}, this.members[i], {index: i});
36470             }
36471         }
36472     },
36473
36474
36475     addMember: function(member, index) {
36476         var members = this.members.slice();
36477         members.splice(index === undefined ? members.length : index, 0, member);
36478         return this.update({members: members});
36479     },
36480
36481
36482     updateMember: function(member, index) {
36483         var members = this.members.slice();
36484         members.splice(index, 1, lodash.extend({}, members[index], member));
36485         return this.update({members: members});
36486     },
36487
36488
36489     removeMember: function(index) {
36490         var members = this.members.slice();
36491         members.splice(index, 1);
36492         return this.update({members: members});
36493     },
36494
36495
36496     removeMembersWithID: function(id) {
36497         var members = lodash.reject(this.members, function(m) { return m.id === id; });
36498         return this.update({members: members});
36499     },
36500
36501
36502     // Wherever a member appears with id `needle.id`, replace it with a member
36503     // with id `replacement.id`, type `replacement.type`, and the original role,
36504     // unless a member already exists with that id and role. Return an updated
36505     // relation.
36506     replaceMember: function(needle, replacement) {
36507         if (!this.memberById(needle.id))
36508             return this;
36509
36510         var members = [];
36511
36512         for (var i = 0; i < this.members.length; i++) {
36513             var member = this.members[i];
36514             if (member.id !== needle.id) {
36515                 members.push(member);
36516             } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
36517                 members.push({id: replacement.id, type: replacement.type, role: member.role});
36518             }
36519         }
36520
36521         return this.update({members: members});
36522     },
36523
36524
36525     asJXON: function(changeset_id) {
36526         var r = {
36527             relation: {
36528                 '@id': this.osmId(),
36529                 '@version': this.version || 0,
36530                 member: lodash.map(this.members, function(member) {
36531                     return {
36532                         keyAttributes: {
36533                             type: member.type,
36534                             role: member.role,
36535                             ref: osmEntity$$1.id.toOSM(member.id)
36536                         }
36537                     };
36538                 }),
36539                 tag: lodash.map(this.tags, function(v, k) {
36540                     return { keyAttributes: { k: k, v: v } };
36541                 })
36542             }
36543         };
36544         if (changeset_id) r.relation['@changeset'] = changeset_id;
36545         return r;
36546     },
36547
36548
36549     asGeoJSON: function(resolver) {
36550         return resolver.transient(this, 'GeoJSON', function () {
36551             if (this.isMultipolygon()) {
36552                 return {
36553                     type: 'MultiPolygon',
36554                     coordinates: this.multipolygon(resolver)
36555                 };
36556             } else {
36557                 return {
36558                     type: 'FeatureCollection',
36559                     properties: this.tags,
36560                     features: this.members.map(function (member) {
36561                         return lodash.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
36562                     })
36563                 };
36564             }
36565         });
36566     },
36567
36568
36569     area: function(resolver) {
36570         return resolver.transient(this, 'area', function() {
36571             return area$1(this.asGeoJSON(resolver));
36572         });
36573     },
36574
36575
36576     isMultipolygon: function() {
36577         return this.tags.type === 'multipolygon';
36578     },
36579
36580
36581     isComplete: function(resolver) {
36582         for (var i = 0; i < this.members.length; i++) {
36583             if (!resolver.hasEntity(this.members[i].id)) {
36584                 return false;
36585             }
36586         }
36587         return true;
36588     },
36589
36590
36591     isRestriction: function() {
36592         return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
36593     },
36594
36595
36596     // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
36597     // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
36598     //
36599     // This corresponds to the structure needed for rendering a multipolygon path using a
36600     // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
36601     //
36602     // In the case of invalid geometries, this function will still return a result which
36603     // includes the nodes of all way members, but some Nds may be unclosed and some inner
36604     // rings not matched with the intended outer ring.
36605     //
36606     multipolygon: function(resolver) {
36607         var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
36608             inners = this.members.filter(function(m) { return 'inner' === m.role; });
36609
36610         outers = osmJoinWays(outers, resolver);
36611         inners = osmJoinWays(inners, resolver);
36612
36613         outers = outers.map(function(outer) { return lodash.map(outer.nodes, 'loc'); });
36614         inners = inners.map(function(inner) { return lodash.map(inner.nodes, 'loc'); });
36615
36616         var result = outers.map(function(o) {
36617             // Heuristic for detecting counterclockwise winding order. Assumes
36618             // that OpenStreetMap polygons are not hemisphere-spanning.
36619             return [area$1({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o];
36620         });
36621
36622         function findOuter(inner) {
36623             var o, outer;
36624
36625             for (o = 0; o < outers.length; o++) {
36626                 outer = outers[o];
36627                 if (geoPolygonContainsPolygon(outer, inner))
36628                     return o;
36629             }
36630
36631             for (o = 0; o < outers.length; o++) {
36632                 outer = outers[o];
36633                 if (geoPolygonIntersectsPolygon(outer, inner, false))
36634                     return o;
36635             }
36636         }
36637
36638         for (var i = 0; i < inners.length; i++) {
36639             var inner = inners[i];
36640
36641             if (area$1({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) {
36642                 inner = inner.reverse();
36643             }
36644
36645             var o = findOuter(inners[i]);
36646             if (o !== undefined)
36647                 result[o].push(inners[i]);
36648             else
36649                 result.push([inners[i]]); // Invalid geometry
36650         }
36651
36652         return result;
36653     }
36654 });
36655
36656 function osmLanes(entity) {
36657     if (entity.type !== 'way') return null;
36658     if (!entity.tags.highway) return null;
36659
36660     var tags = entity.tags;
36661     var isOneWay = entity.isOneWay();
36662     var laneCount = getLaneCount(tags, isOneWay);
36663     var maxspeed = parseMaxspeed(tags);
36664
36665     var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
36666     var forward = laneDirections.forward;
36667     var backward = laneDirections.backward;
36668     var bothways = laneDirections.bothways;
36669
36670     // parse the piped string 'x|y|z' format
36671     var turnLanes = {};
36672     turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
36673     turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
36674     turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
36675
36676     var maxspeedLanes = {};
36677     maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
36678     maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
36679     maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
36680
36681     var psvLanes = {};
36682     psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
36683     psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
36684     psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
36685
36686     var busLanes = {};
36687     busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
36688     busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
36689     busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
36690
36691     var taxiLanes = {};
36692     taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
36693     taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
36694     taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
36695
36696     var hovLanes = {};
36697     hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
36698     hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
36699     hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
36700
36701     var hgvLanes = {};
36702     hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
36703     hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
36704     hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
36705
36706     var bicyclewayLanes = {};
36707     bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
36708     bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
36709     bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
36710
36711     var lanesObj = {
36712         forward: [],
36713         backward: [],
36714         unspecified: []
36715     };
36716
36717     // map forward/backward/unspecified of each lane type to lanesObj
36718     mapToLanesObj(lanesObj, turnLanes, 'turnLane');
36719     mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
36720     mapToLanesObj(lanesObj, psvLanes, 'psv');
36721     mapToLanesObj(lanesObj, busLanes, 'bus');
36722     mapToLanesObj(lanesObj, taxiLanes, 'taxi');
36723     mapToLanesObj(lanesObj, hovLanes, 'hov');
36724     mapToLanesObj(lanesObj, hgvLanes, 'hgv');
36725     mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
36726
36727     return {
36728         metadata: {
36729             count: laneCount,
36730             oneway: isOneWay,
36731             forward: forward,
36732             backward: backward,
36733             bothways: bothways,
36734             turnLanes: turnLanes,
36735             maxspeed: maxspeed,
36736             maxspeedLanes: maxspeedLanes,
36737             psvLanes: psvLanes,
36738             busLanes: busLanes,
36739             taxiLanes: taxiLanes,
36740             hovLanes: hovLanes,
36741             hgvLanes: hgvLanes,
36742             bicyclewayLanes: bicyclewayLanes
36743         },
36744         lanes: lanesObj
36745     };
36746 }
36747
36748
36749 function getLaneCount(tags, isOneWay) {
36750     var count;
36751     if (tags.lanes) {
36752         count = parseInt(tags.lanes, 10);
36753         if (count > 0) {
36754             return count;
36755         }
36756     }
36757
36758
36759     switch (tags.highway) {
36760         case 'trunk':
36761         case 'motorway':
36762             count = isOneWay ? 2 : 4;
36763             break;
36764         default:
36765             count = isOneWay ? 1 : 2;
36766             break;
36767     }
36768
36769     return count;
36770 }
36771
36772
36773 function parseMaxspeed(tags) {
36774     var maxspeed = tags.maxspeed;
36775     if (lodash.isNumber(maxspeed)) return maxspeed;
36776     if (lodash.isString(maxspeed)) {
36777         maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g);
36778         if (!maxspeed) return;
36779         return parseInt(maxspeed, 10);
36780     }
36781 }
36782
36783
36784 function parseLaneDirections(tags, isOneWay, laneCount) {
36785     var forward = parseInt(tags['lanes:forward'], 10);
36786     var backward = parseInt(tags['lanes:backward'], 10);
36787     var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
36788
36789     if (parseInt(tags.oneway, 10) === -1) {
36790         forward = 0;
36791         bothways = 0;
36792         backward = laneCount;
36793     }
36794     else if (isOneWay) {
36795         forward = laneCount;
36796         bothways = 0;
36797         backward = 0;
36798     }
36799     else if (lodash.isNaN(forward) && lodash.isNaN(backward)) {
36800         backward = Math.floor((laneCount - bothways) / 2);
36801         forward = laneCount - bothways - backward;
36802     }
36803     else if (lodash.isNaN(forward)) {
36804         if (backward > laneCount - bothways) {
36805             backward = laneCount - bothways;
36806         }
36807         forward = laneCount - bothways - backward;
36808     }
36809     else if (lodash.isNaN(backward)) {
36810         if (forward > laneCount - bothways) {
36811             forward = laneCount - bothways;
36812         }
36813         backward = laneCount - bothways - forward;
36814     }
36815     return {
36816         forward: forward,
36817         backward: backward,
36818         bothways: bothways
36819     };
36820 }
36821
36822
36823 function parseTurnLanes(tag){
36824     if (!tag) return;
36825
36826     var validValues = [
36827         'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right',
36828         'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'
36829     ];
36830
36831     return tag.split('|')
36832         .map(function (s) {
36833             if (s === '') s = 'none';
36834             return s.split(';')
36835                 .map(function (d) {
36836                     return validValues.indexOf(d) === -1 ? 'unknown': d;
36837                 });
36838         });
36839 }
36840
36841
36842 function parseMaxspeedLanes(tag, maxspeed) {
36843     if (!tag) return;
36844
36845     return tag.split('|')
36846         .map(function (s) {
36847             if (s === 'none') return s;
36848             var m = parseInt(s, 10);
36849             if (s === '' || m === maxspeed) return null;
36850             return lodash.isNaN(m) ? 'unknown': m;
36851         });
36852 }
36853
36854
36855 function parseMiscLanes(tag) {
36856     if (!tag) return;
36857
36858     var validValues = [
36859         'yes', 'no', 'designated'
36860     ];
36861
36862     return tag.split('|')
36863         .map(function (s) {
36864             if (s === '') s = 'no';
36865             return validValues.indexOf(s) === -1 ? 'unknown': s;
36866         });
36867 }
36868
36869
36870 function parseBicycleWay(tag) {
36871     if (!tag) return;
36872
36873     var validValues = [
36874         'yes', 'no', 'designated', 'lane'
36875     ];
36876
36877     return tag.split('|')
36878         .map(function (s) {
36879             if (s === '') s = 'no';
36880             return validValues.indexOf(s) === -1 ? 'unknown': s;
36881         });
36882 }
36883
36884
36885 function mapToLanesObj(lanesObj, data, key) {
36886     if (data.forward) data.forward.forEach(function(l, i) {
36887         if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
36888         lanesObj.forward[i][key] = l;
36889     });
36890     if (data.backward) data.backward.forEach(function(l, i) {
36891         if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
36892         lanesObj.backward[i][key] = l;
36893     });
36894     if (data.unspecified) data.unspecified.forEach(function(l, i) {
36895         if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
36896         lanesObj.unspecified[i][key] = l;
36897     });
36898 }
36899
36900 var translations = Object.create(null);
36901
36902 var currentLocale = 'en';
36903 var textDirection = 'ltr';
36904
36905 function setLocale(_) {
36906     if (translations[_] !== undefined) {
36907         currentLocale = _;
36908     } else if (translations[_.split('-')[0]]) {
36909         currentLocale = _.split('-')[0];
36910     }
36911 }
36912
36913 function addTranslation(id, value) {
36914     translations[id] = value;
36915 }
36916
36917 /**
36918  * Given a string identifier, try to find that string in the current
36919  * language, and return it.
36920  *
36921  * @param {string} s string identifier
36922  * @returns {string?} locale string
36923  */
36924 function t(s, o, loc) {
36925     loc = loc || currentLocale;
36926
36927     var path = s.split('.').reverse();
36928     var rep = translations[loc];
36929
36930     while (rep !== undefined && path.length) rep = rep[path.pop()];
36931
36932     if (rep !== undefined) {
36933         if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
36934         return rep;
36935     }
36936
36937     if (loc !== 'en') {
36938         return t(s, o, 'en');
36939     }
36940
36941     if (o && 'default' in o) {
36942         return o.default;
36943     }
36944
36945     var missing = 'Missing ' + loc + ' translation: ' + s;
36946     if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
36947
36948     return missing;
36949 }
36950
36951 /**
36952  * Given string 'ltr' or 'rtl', save that setting
36953  *
36954  * @param {string} s ltr or rtl
36955  */
36956
36957 function setTextDirection(dir) {
36958     textDirection = dir;
36959 }
36960
36961 var detected;
36962
36963 function utilDetect(force) {
36964     if (detected && !force) return detected;
36965     detected = {};
36966
36967     var ua = navigator.userAgent,
36968         m = null;
36969
36970     m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i);   // Edge
36971     if (m !== null) {
36972         detected.browser = m[1];
36973         detected.version = m[2];
36974     }
36975     if (!detected.browser) {
36976         m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i);   // IE11
36977         if (m !== null) {
36978             detected.browser = 'msie';
36979             detected.version = m[1];
36980         }
36981     }
36982     if (!detected.browser) {
36983         m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i);   // Opera 15+
36984         if (m !== null) {
36985             detected.browser = 'Opera';
36986             detected.version = m[2];
36987         }
36988     }
36989     if (!detected.browser) {
36990         m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
36991         if (m !== null) {
36992             detected.browser = m[1];
36993             detected.version = m[2];
36994             m = ua.match(/version\/([\.\d]+)/i);
36995             if (m !== null) detected.version = m[1];
36996         }
36997     }
36998     if (!detected.browser) {
36999         detected.browser = navigator.appName;
37000         detected.version = navigator.appVersion;
37001     }
37002
37003     // keep major.minor version only..
37004     detected.version = detected.version.split(/\W/).slice(0,2).join('.');
37005
37006     if (detected.browser.toLowerCase() === 'msie') {
37007         detected.ie = true;
37008         detected.browser = 'Internet Explorer';
37009         detected.support = parseFloat(detected.version) >= 11;
37010     } else {
37011         detected.ie = false;
37012         detected.support = true;
37013     }
37014
37015     // Added due to incomplete svg style support. See #715
37016     detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
37017
37018     detected.locale = (navigator.languages && navigator.languages.length)
37019         ? navigator.languages[0] : (navigator.language || navigator.userLanguage || 'en-US');
37020
37021     // Loaded locale is stored in currentLocale
37022     // return that instead (except in the situation where 'en' might override 'en-US')
37023     var loadedLocale = currentLocale || 'en';
37024     if (loadedLocale !== 'en') {
37025         detected.locale = loadedLocale;
37026     }
37027
37028     // detect text direction
37029     var q = utilStringQs(window.location.hash.substring(1));
37030     if (['ar', 'fa', 'iw', 'he', 'dv'].indexOf(detected.locale.split('-')[0]) > -1 || q.hasOwnProperty('rtl')) {
37031         detected.textDirection = 'rtl';
37032     } else {
37033         detected.textDirection = 'ltr';
37034     }
37035     setTextDirection(detected.textDirection);
37036
37037     detected.host = window.location && (window.location.origin + window.location.pathname);
37038
37039     detected.filedrop = (window.FileReader && 'ondrop' in window);
37040
37041     function nav(x) {
37042         return navigator.userAgent.indexOf(x) !== -1;
37043     }
37044
37045     if (nav('Win')) {
37046         detected.os = 'win';
37047         detected.platform = 'Windows';
37048     }
37049     else if (nav('Mac')) {
37050         detected.os = 'mac';
37051         detected.platform = 'Macintosh';
37052     }
37053     else if (nav('X11') || nav('Linux')) {
37054         detected.os = 'linux';
37055         detected.platform = 'Linux';
37056     }
37057     else {
37058         detected.os = 'win';
37059         detected.platform = 'Unknown';
37060     }
37061
37062     return detected;
37063 }
37064
37065 var remove$1 = removeDiacritics;
37066
37067 var replacementList = [
37068   {
37069     base: ' ',
37070     chars: "\u00A0",
37071   }, {
37072     base: '0',
37073     chars: "\u07C0",
37074   }, {
37075     base: 'A',
37076     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",
37077   }, {
37078     base: 'AA',
37079     chars: "\uA732",
37080   }, {
37081     base: 'AE',
37082     chars: "\u00C6\u01FC\u01E2",
37083   }, {
37084     base: 'AO',
37085     chars: "\uA734",
37086   }, {
37087     base: 'AU',
37088     chars: "\uA736",
37089   }, {
37090     base: 'AV',
37091     chars: "\uA738\uA73A",
37092   }, {
37093     base: 'AY',
37094     chars: "\uA73C",
37095   }, {
37096     base: 'B',
37097     chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181",
37098   }, {
37099     base: 'C',
37100     chars: "\u24b8\uff23\uA73E\u1E08\u0106\u0043\u0108\u010A\u010C\u00C7\u0187\u023B",
37101   }, {
37102     base: 'D',
37103     chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779",
37104   }, {
37105     base: 'Dh',
37106     chars: "\u00D0",
37107   }, {
37108     base: 'DZ',
37109     chars: "\u01F1\u01C4",
37110   }, {
37111     base: 'Dz',
37112     chars: "\u01F2\u01C5",
37113   }, {
37114     base: 'E',
37115     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",
37116   }, {
37117     base: 'F',
37118     chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B",
37119   }, {
37120     base: 'G',
37121     chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262",
37122   }, {
37123     base: 'H',
37124     chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D",
37125   }, {
37126     base: 'I',
37127     chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197",
37128   }, {
37129     base: 'J',
37130     chars: "\u24BF\uFF2A\u0134\u0248\u0237",
37131   }, {
37132     base: 'K',
37133     chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2",
37134   }, {
37135     base: 'L',
37136     chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780",
37137   }, {
37138     base: 'LJ',
37139     chars: "\u01C7",
37140   }, {
37141     base: 'Lj',
37142     chars: "\u01C8",
37143   }, {
37144     base: 'M',
37145     chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB",
37146   }, {
37147     base: 'N',
37148     chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E",
37149   }, {
37150     base: 'NJ',
37151     chars: "\u01CA",
37152   }, {
37153     base: 'Nj',
37154     chars: "\u01CB",
37155   }, {
37156     base: 'O',
37157     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",
37158   }, {
37159     base: 'OE',
37160     chars: "\u0152",
37161   }, {
37162     base: 'OI',
37163     chars: "\u01A2",
37164   }, {
37165     base: 'OO',
37166     chars: "\uA74E",
37167   }, {
37168     base: 'OU',
37169     chars: "\u0222",
37170   }, {
37171     base: 'P',
37172     chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754",
37173   }, {
37174     base: 'Q',
37175     chars: "\u24C6\uFF31\uA756\uA758\u024A",
37176   }, {
37177     base: 'R',
37178     chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782",
37179   }, {
37180     base: 'S',
37181     chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784",
37182   }, {
37183     base: 'T',
37184     chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786",
37185   }, {
37186     base: 'Th',
37187     chars: "\u00DE",
37188   }, {
37189     base: 'TZ',
37190     chars: "\uA728",
37191   }, {
37192     base: 'U',
37193     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",
37194   }, {
37195     base: 'V',
37196     chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245",
37197   }, {
37198     base: 'VY',
37199     chars: "\uA760",
37200   }, {
37201     base: 'W',
37202     chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72",
37203   }, {
37204     base: 'X',
37205     chars: "\u24CD\uFF38\u1E8A\u1E8C",
37206   }, {
37207     base: 'Y',
37208     chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE",
37209   }, {
37210     base: 'Z',
37211     chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762",
37212   }, {
37213     base: 'a',
37214     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",
37215   }, {
37216     base: 'aa',
37217     chars: "\uA733",
37218   }, {
37219     base: 'ae',
37220     chars: "\u00E6\u01FD\u01E3",
37221   }, {
37222     base: 'ao',
37223     chars: "\uA735",
37224   }, {
37225     base: 'au',
37226     chars: "\uA737",
37227   }, {
37228     base: 'av',
37229     chars: "\uA739\uA73B",
37230   }, {
37231     base: 'ay',
37232     chars: "\uA73D",
37233   }, {
37234     base: 'b',
37235     chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182",
37236   }, {
37237     base: 'c',
37238     chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184",
37239   }, {
37240     base: 'd',
37241     chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA",
37242   }, {
37243     base: 'dh',
37244     chars: "\u00F0",
37245   }, {
37246     base: 'dz',
37247     chars: "\u01F3\u01C6",
37248   }, {
37249     base: 'e',
37250     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",
37251   }, {
37252     base: 'f',
37253     chars: "\u24D5\uFF46\u1E1F\u0192",
37254   }, {
37255     base: 'ff',
37256     chars: "\uFB00",
37257   }, {
37258     base: 'fi',
37259     chars: "\uFB01",
37260   }, {
37261     base: 'fl',
37262     chars: "\uFB02",
37263   }, {
37264     base: 'ffi',
37265     chars: "\uFB03",
37266   }, {
37267     base: 'ffl',
37268     chars: "\uFB04",
37269   }, {
37270     base: 'g',
37271     chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79",
37272   }, {
37273     base: 'h',
37274     chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265",
37275   }, {
37276     base: 'hv',
37277     chars: "\u0195",
37278   }, {
37279     base: 'i',
37280     chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131",
37281   }, {
37282     base: 'j',
37283     chars: "\u24D9\uFF4A\u0135\u01F0\u0249",
37284   }, {
37285     base: 'k',
37286     chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3",
37287   }, {
37288     base: 'l',
37289     chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D",
37290   }, {
37291     base: 'lj',
37292     chars: "\u01C9",
37293   }, {
37294     base: 'm',
37295     chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F",
37296   }, {
37297     base: 'n',
37298     chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509",
37299   }, {
37300     base: 'nj',
37301     chars: "\u01CC",
37302   }, {
37303     base: 'o',
37304     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",
37305   }, {
37306     base: 'oe',
37307     chars: "\u0153",
37308   }, {
37309     base: 'oi',
37310     chars: "\u01A3",
37311   }, {
37312     base: 'oo',
37313     chars: "\uA74F",
37314   }, {
37315     base: 'ou',
37316     chars: "\u0223",
37317   }, {
37318     base: 'p',
37319     chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1",
37320   }, {
37321     base: 'q',
37322     chars: "\u24E0\uFF51\u024B\uA757\uA759",
37323   }, {
37324     base: 'r',
37325     chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783",
37326   }, {
37327     base: 's',
37328     chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282",
37329   }, {
37330     base: 'ss',
37331     chars: "\xDF",
37332   }, {
37333     base: 't',
37334     chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787",
37335   }, {
37336     base: 'th',
37337     chars: "\u00FE",
37338   }, {
37339     base: 'tz',
37340     chars: "\uA729",
37341   }, {
37342     base: 'u',
37343     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",
37344   }, {
37345     base: 'v',
37346     chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C",
37347   }, {
37348     base: 'vy',
37349     chars: "\uA761",
37350   }, {
37351     base: 'w',
37352     chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73",
37353   }, {
37354     base: 'x',
37355     chars: "\u24E7\uFF58\u1E8B\u1E8D",
37356   }, {
37357     base: 'y',
37358     chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF",
37359   }, {
37360     base: 'z',
37361     chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763",
37362   }
37363 ];
37364
37365 var diacriticsMap = {};
37366 for (var i = 0; i < replacementList.length; i += 1) {
37367   var chars = replacementList[i].chars;
37368   for (var j = 0; j < chars.length; j += 1) {
37369     diacriticsMap[chars[j]] = replacementList[i].base;
37370   }
37371 }
37372
37373 function removeDiacritics(str) {
37374   return str.replace(/[^\u0000-\u007e]/g, function(c) {
37375     return diacriticsMap[c] || c;
37376   });
37377 }
37378
37379 function utilTagText(entity) {
37380     return entries(entity.tags).map(function(e) {
37381         return e.key + '=' + e.value;
37382     }).join(', ');
37383 }
37384
37385
37386 function utilEntitySelector(ids) {
37387     return ids.length ? '.' + ids.join(',.') : 'nothing';
37388 }
37389
37390
37391 function utilEntityOrMemberSelector(ids, graph) {
37392     var s = utilEntitySelector(ids);
37393
37394     ids.forEach(function(id) {
37395         var entity = graph.hasEntity(id);
37396         if (entity && entity.type === 'relation') {
37397             entity.members.forEach(function(member) {
37398                 s += ',.' + member.id;
37399             });
37400         }
37401     });
37402
37403     return s;
37404 }
37405
37406
37407 function utilDisplayName(entity) {
37408     var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0],
37409         name = entity.tags[localizedNameKey] || entity.tags.name || '',
37410         network = entity.tags.cycle_network || entity.tags.network;
37411     if (!name && entity.tags.ref) {
37412         name = entity.tags.ref;
37413         if (network) {
37414             name = network + ' ' + name;
37415         }
37416     }
37417     return name;
37418 }
37419
37420
37421 function utilDisplayType(id) {
37422     return {
37423         n: t('inspector.node'),
37424         w: t('inspector.way'),
37425         r: t('inspector.relation')
37426     }[id.charAt(0)];
37427 }
37428
37429
37430 function utilStringQs(str) {
37431     return str.split('&').reduce(function(obj, pair){
37432         var parts = pair.split('=');
37433         if (parts.length === 2) {
37434             obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
37435         }
37436         return obj;
37437     }, {});
37438 }
37439
37440
37441 function utilQsString(obj, noencode) {
37442     function softEncode(s) {
37443       // encode everything except special characters used in certain hash parameters:
37444       // "/" in map states, ":", ",", {" and "}" in background
37445       return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
37446     }
37447     return Object.keys(obj).sort().map(function(key) {
37448         return encodeURIComponent(key) + '=' + (
37449             noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
37450     }).join('&');
37451 }
37452
37453
37454 function utilPrefixDOMProperty(property) {
37455     var prefixes = ['webkit', 'ms', 'moz', 'o'],
37456         i = -1,
37457         n = prefixes.length,
37458         s = document.body;
37459
37460     if (property in s)
37461         return property;
37462
37463     property = property.substr(0, 1).toUpperCase() + property.substr(1);
37464
37465     while (++i < n)
37466         if (prefixes[i] + property in s)
37467             return prefixes[i] + property;
37468
37469     return false;
37470 }
37471
37472
37473 function utilPrefixCSSProperty(property) {
37474     var prefixes = ['webkit', 'ms', 'Moz', 'O'],
37475         i = -1,
37476         n = prefixes.length,
37477         s = document.body.style;
37478
37479     if (property.toLowerCase() in s)
37480         return property.toLowerCase();
37481
37482     while (++i < n)
37483         if (prefixes[i] + property in s)
37484             return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37485
37486     return false;
37487 }
37488
37489
37490 var transformProperty;
37491 function utilSetTransform(el, x, y, scale) {
37492     var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform'),
37493         translate = utilDetect().opera ?
37494             'translate('   + x + 'px,' + y + 'px)' :
37495             'translate3d(' + x + 'px,' + y + 'px,0)';
37496     return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37497 }
37498
37499
37500 // Calculates Levenshtein distance between two strings
37501 // see:  https://en.wikipedia.org/wiki/Levenshtein_distance
37502 // first converts the strings to lowercase and replaces diacritic marks with ascii equilivants.
37503 function utilEditDistance(a, b) {
37504     a = remove$1(a.toLowerCase());
37505     b = remove$1(b.toLowerCase());
37506     if (a.length === 0) return b.length;
37507     if (b.length === 0) return a.length;
37508     var matrix = [];
37509     for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
37510     for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
37511     for (i = 1; i <= b.length; i++) {
37512         for (j = 1; j <= a.length; j++) {
37513             if (b.charAt(i-1) === a.charAt(j-1)) {
37514                 matrix[i][j] = matrix[i-1][j-1];
37515             } else {
37516                 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
37517                     Math.min(matrix[i][j-1] + 1, // insertion
37518                     matrix[i-1][j] + 1)); // deletion
37519             }
37520         }
37521     }
37522     return matrix[b.length][a.length];
37523 }
37524
37525
37526 // a d3.mouse-alike which
37527 // 1. Only works on HTML elements, not SVG
37528 // 2. Does not cause style recalculation
37529 function utilFastMouse(container) {
37530     var rect = container.getBoundingClientRect(),
37531         rectLeft = rect.left,
37532         rectTop = rect.top,
37533         clientLeft = +container.clientLeft,
37534         clientTop = +container.clientTop;
37535     if (textDirection === 'rtl') {
37536         rectLeft = 0;
37537     }
37538     return function(e) {
37539         return [
37540             e.clientX - rectLeft - clientLeft,
37541             e.clientY - rectTop - clientTop];
37542     };
37543 }
37544
37545
37546 /* eslint-disable no-proto */
37547 var utilGetPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
37548 /* eslint-enable no-proto */
37549
37550
37551 function utilAsyncMap(inputs, func, callback) {
37552     var remaining = inputs.length,
37553         results = [],
37554         errors = [];
37555
37556     inputs.forEach(function(d, i) {
37557         func(d, function done(err, data) {
37558             errors[i] = err;
37559             results[i] = data;
37560             remaining--;
37561             if (!remaining) callback(errors, results);
37562         });
37563     });
37564 }
37565
37566
37567 // wraps an index to an interval [0..length-1]
37568 function utilWrap(index, length) {
37569     if (index < 0)
37570         index += Math.ceil(-index/length)*length;
37571     return index % length;
37572 }
37573
37574
37575 /**
37576  * a replacement for functor
37577  *
37578  * @param {*} value any value
37579  * @returns {Function} a function that returns that value or the value if it's a function
37580  */
37581 function utilFunctor(value) {
37582     if (typeof value === 'function') return value;
37583     return function() {
37584         return value;
37585     };
37586 }
37587
37588 // A per-domain session mutex backed by a cookie and dead man's
37589 // switch. If the session crashes, the mutex will auto-release
37590 // after 5 seconds.
37591
37592 function utilSessionMutex(name) {
37593     var mutex = {},
37594         intervalID;
37595
37596     function renew() {
37597         var expires = new Date();
37598         expires.setSeconds(expires.getSeconds() + 5);
37599         document.cookie = name + '=1; expires=' + expires.toUTCString();
37600     }
37601
37602     mutex.lock = function() {
37603         if (intervalID) return true;
37604         var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
37605         if (cookie) return false;
37606         renew();
37607         intervalID = window.setInterval(renew, 4000);
37608         return true;
37609     };
37610
37611     mutex.unlock = function() {
37612         if (!intervalID) return;
37613         document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
37614         clearInterval(intervalID);
37615         intervalID = null;
37616     };
37617
37618     mutex.locked = function() {
37619         return !!intervalID;
37620     };
37621
37622     return mutex;
37623 }
37624
37625 function utilSuggestNames(preset, suggestions) {
37626     preset = preset.id.split('/', 2);
37627     var k = preset[0],
37628         v = preset[1];
37629
37630     return function(value, callback) {
37631         var result = [];
37632         if (value && value.length > 2) {
37633             if (suggestions[k] && suggestions[k][v]) {
37634                 for (var sugg in suggestions[k][v]) {
37635                     var dist = utilEditDistance(value, sugg.substring(0, value.length));
37636                     if (dist < 3) {
37637                         result.push({
37638                             title: sugg,
37639                             value: sugg,
37640                             dist: dist
37641                         });
37642                     }
37643                 }
37644             }
37645             result.sort(function(a, b) {
37646                 return a.dist - b.dist;
37647             });
37648         }
37649         result = result.slice(0,3);
37650         callback(result);
37651     };
37652 }
37653
37654 function utilTriggerEvent(target, type) {
37655     target.each(function() {
37656         var evt = document.createEvent('HTMLEvents');
37657         evt.initEvent(type, true, true);
37658         this.dispatchEvent(evt);
37659     });
37660 }
37661
37662 // Like selection.property('value', ...), but avoids no-op value sets,
37663 // which can result in layout/repaint thrashing in some situations.
37664 function utilGetSetValue(selection, value) {
37665     function d3_selection_value(value) {
37666         function valueNull() {
37667             delete this.value;
37668         }
37669
37670         function valueConstant() {
37671             if (this.value !== value) {
37672                 this.value = value;
37673             }
37674         }
37675
37676         function valueFunction() {
37677             var x = value.apply(this, arguments);
37678             if (x == null) {
37679                 delete this.value;
37680             } else if (this.value !== x) {
37681                 this.value = x;
37682             }
37683         }
37684
37685         return value == null
37686             ? valueNull : (typeof value === 'function'
37687             ? valueFunction : valueConstant);
37688     }
37689
37690     if (arguments.length === 1) {
37691         return selection.property('value');
37692     }
37693
37694     return selection.each(d3_selection_value(value));
37695 }
37696
37697 function validationDeprecatedTag() {
37698
37699     var validation = function(changes) {
37700         var warnings = [];
37701         for (var i = 0; i < changes.created.length; i++) {
37702             var change = changes.created[i],
37703                 deprecatedTags = change.deprecatedTags();
37704
37705             if (!lodash.isEmpty(deprecatedTags)) {
37706                 var tags = utilTagText({ tags: deprecatedTags });
37707                 warnings.push({
37708                     id: 'deprecated_tags',
37709                     message: t('validations.deprecated_tags', { tags: tags }),
37710                     entity: change
37711                 });
37712             }
37713         }
37714
37715         return warnings;
37716     };
37717
37718
37719     return validation;
37720 }
37721
37722 function validationManyDeletions() {
37723     var threshold = 100;
37724
37725     var validation = function(changes) {
37726         var warnings = [];
37727         if (changes.deleted.length > threshold) {
37728             warnings.push({
37729                 id: 'many_deletions',
37730                 message: t('validations.many_deletions', { n: changes.deleted.length })
37731             });
37732         }
37733
37734         return warnings;
37735     };
37736
37737
37738     return validation;
37739 }
37740
37741 function validationMissingTag() {
37742
37743     // Slightly stricter check than Entity#isUsed (#3091)
37744     function hasTags(entity, graph) {
37745         return lodash.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
37746             graph.parentRelations(entity).length > 0;
37747     }
37748
37749     var validation = function(changes, graph) {
37750         var warnings = [];
37751         for (var i = 0; i < changes.created.length; i++) {
37752             var change = changes.created[i],
37753                 geometry = change.geometry(graph);
37754
37755             if ((geometry === 'point' || geometry === 'line' || geometry === 'area') && !hasTags(change, graph)) {
37756                 warnings.push({
37757                     id: 'missing_tag',
37758                     message: t('validations.untagged_' + geometry),
37759                     tooltip: t('validations.untagged_' + geometry + '_tooltip'),
37760                     entity: change
37761                 });
37762             }
37763         }
37764
37765         return warnings;
37766     };
37767
37768
37769     return validation;
37770 }
37771
37772 // https://github.com/openstreetmap/josm/blob/mirror/src/org/
37773 // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
37774 function validationTagSuggestsArea() {
37775
37776     function tagSuggestsArea(tags) {
37777         if (lodash.isEmpty(tags)) return false;
37778
37779         var presence = ['landuse', 'amenities', 'tourism', 'shop'];
37780         for (var i = 0; i < presence.length; i++) {
37781             if (tags[presence[i]] !== undefined) {
37782                 return presence[i] + '=' + tags[presence[i]];
37783             }
37784         }
37785
37786         if (tags.building && tags.building === 'yes') return 'building=yes';
37787     }
37788
37789
37790     var validation = function(changes, graph) {
37791         var warnings = [];
37792         for (var i = 0; i < changes.created.length; i++) {
37793             var change = changes.created[i],
37794                 geometry = change.geometry(graph),
37795                 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
37796
37797             if (suggestion) {
37798                 warnings.push({
37799                     id: 'tag_suggests_area',
37800                     message: t('validations.tag_suggests_area', { tag: suggestion }),
37801                     entity: change
37802                 });
37803             }
37804         }
37805
37806         return warnings;
37807     };
37808
37809
37810     return validation;
37811 }
37812
37813
37814
37815 var Validations = Object.freeze({
37816         validationDeprecatedTag: validationDeprecatedTag,
37817         validationManyDeletions: validationManyDeletions,
37818         validationMissingTag: validationMissingTag,
37819         validationTagSuggestsArea: validationTagSuggestsArea
37820 });
37821
37822 /*
37823     iD.Difference represents the difference between two graphs.
37824     It knows how to calculate the set of entities that were
37825     created, modified, or deleted, and also contains the logic
37826     for recursively extending a difference to the complete set
37827     of entities that will require a redraw, taking into account
37828     child and parent relationships.
37829  */
37830 function coreDifference(base, head) {
37831     var changes = {},
37832         difference = {},
37833         length = 0;
37834
37835
37836     function changed(h, b) {
37837         return h !== b && !lodash.isEqual(lodash.omit(h, 'v'), lodash.omit(b, 'v'));
37838     }
37839
37840
37841     lodash.each(head.entities, function(h, id) {
37842         var b = base.entities[id];
37843         if (changed(h, b)) {
37844             changes[id] = {base: b, head: h};
37845             length++;
37846         }
37847     });
37848
37849
37850     lodash.each(base.entities, function(b, id) {
37851         var h = head.entities[id];
37852         if (!changes[id] && changed(h, b)) {
37853             changes[id] = {base: b, head: h};
37854             length++;
37855         }
37856     });
37857
37858
37859     function addParents(parents, result) {
37860         for (var i = 0; i < parents.length; i++) {
37861             var parent = parents[i];
37862
37863             if (parent.id in result)
37864                 continue;
37865
37866             result[parent.id] = parent;
37867             addParents(head.parentRelations(parent), result);
37868         }
37869     }
37870
37871
37872     difference.length = function() {
37873         return length;
37874     };
37875
37876
37877     difference.changes = function() {
37878         return changes;
37879     };
37880
37881
37882     difference.extantIDs = function() {
37883         var result = [];
37884         lodash.each(changes, function(change, id) {
37885             if (change.head) result.push(id);
37886         });
37887         return result;
37888     };
37889
37890
37891     difference.modified = 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.created = function() {
37901         var result = [];
37902         lodash.each(changes, function(change) {
37903             if (!change.base && change.head) result.push(change.head);
37904         });
37905         return result;
37906     };
37907
37908
37909     difference.deleted = function() {
37910         var result = [];
37911         lodash.each(changes, function(change) {
37912             if (change.base && !change.head) result.push(change.base);
37913         });
37914         return result;
37915     };
37916
37917
37918     difference.summary = function() {
37919         var relevant = {};
37920
37921         function addEntity(entity, graph, changeType) {
37922             relevant[entity.id] = {
37923                 entity: entity,
37924                 graph: graph,
37925                 changeType: changeType
37926             };
37927         }
37928
37929         function addParents(entity) {
37930             var parents = head.parentWays(entity);
37931             for (var j = parents.length - 1; j >= 0; j--) {
37932                 var parent = parents[j];
37933                 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
37934             }
37935         }
37936
37937         lodash.each(changes, function(change) {
37938             if (change.head && change.head.geometry(head) !== 'vertex') {
37939                 addEntity(change.head, head, change.base ? 'modified' : 'created');
37940
37941             } else if (change.base && change.base.geometry(base) !== 'vertex') {
37942                 addEntity(change.base, base, 'deleted');
37943
37944             } else if (change.base && change.head) { // modified vertex
37945                 var moved    = !lodash.isEqual(change.base.loc,  change.head.loc),
37946                     retagged = !lodash.isEqual(change.base.tags, change.head.tags);
37947
37948                 if (moved) {
37949                     addParents(change.head);
37950                 }
37951
37952                 if (retagged || (moved && change.head.hasInterestingTags())) {
37953                     addEntity(change.head, head, 'modified');
37954                 }
37955
37956             } else if (change.head && change.head.hasInterestingTags()) { // created vertex
37957                 addEntity(change.head, head, 'created');
37958
37959             } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
37960                 addEntity(change.base, base, 'deleted');
37961             }
37962         });
37963
37964         return values(relevant);
37965     };
37966
37967
37968     difference.complete = function(extent$$1) {
37969         var result = {}, id, change;
37970
37971         for (id in changes) {
37972             change = changes[id];
37973
37974             var h = change.head,
37975                 b = change.base,
37976                 entity = h || b;
37977
37978             if (extent$$1 &&
37979                 (!h || !h.intersects(extent$$1, head)) &&
37980                 (!b || !b.intersects(extent$$1, base)))
37981                 continue;
37982
37983             result[id] = h;
37984
37985             if (entity.type === 'way') {
37986                 var nh = h ? h.nodes : [],
37987                     nb = b ? b.nodes : [],
37988                     diff, i;
37989
37990                 diff = lodash.difference(nh, nb);
37991                 for (i = 0; i < diff.length; i++) {
37992                     result[diff[i]] = head.hasEntity(diff[i]);
37993                 }
37994
37995                 diff = lodash.difference(nb, nh);
37996                 for (i = 0; i < diff.length; i++) {
37997                     result[diff[i]] = head.hasEntity(diff[i]);
37998                 }
37999             }
38000
38001             addParents(head.parentWays(entity), result);
38002             addParents(head.parentRelations(entity), result);
38003         }
38004
38005         return result;
38006     };
38007
38008
38009     return difference;
38010 }
38011
38012 function coreGraph$$1(other, mutable) {
38013     if (!(this instanceof coreGraph$$1)) return new coreGraph$$1(other, mutable);
38014
38015     if (other instanceof coreGraph$$1) {
38016         var base = other.base();
38017         this.entities = lodash.assign(Object.create(base.entities), other.entities);
38018         this._parentWays = lodash.assign(Object.create(base.parentWays), other._parentWays);
38019         this._parentRels = lodash.assign(Object.create(base.parentRels), other._parentRels);
38020
38021     } else {
38022         this.entities = Object.create({});
38023         this._parentWays = Object.create({});
38024         this._parentRels = Object.create({});
38025         this.rebase(other || [], [this]);
38026     }
38027
38028     this.transients = {};
38029     this._childNodes = {};
38030     this.frozen = !mutable;
38031 }
38032
38033
38034 coreGraph$$1.prototype = {
38035
38036     hasEntity: function(id) {
38037         return this.entities[id];
38038     },
38039
38040
38041     entity: function(id) {
38042         var entity = this.entities[id];
38043         if (!entity) {
38044             throw new Error('entity ' + id + ' not found');
38045         }
38046         return entity;
38047     },
38048
38049
38050     transient: function(entity, key, fn) {
38051         var id = entity.id,
38052             transients = this.transients[id] ||
38053             (this.transients[id] = {});
38054
38055         if (transients[key] !== undefined) {
38056             return transients[key];
38057         }
38058
38059         transients[key] = fn.call(entity);
38060
38061         return transients[key];
38062     },
38063
38064
38065     parentWays: function(entity) {
38066         var parents = this._parentWays[entity.id],
38067             result = [];
38068
38069         if (parents) {
38070             for (var i = 0; i < parents.length; i++) {
38071                 result.push(this.entity(parents[i]));
38072             }
38073         }
38074         return result;
38075     },
38076
38077
38078     isPoi: function(entity) {
38079         var parentWays = this._parentWays[entity.id];
38080         return !parentWays || parentWays.length === 0;
38081     },
38082
38083
38084     isShared: function(entity) {
38085         var parentWays = this._parentWays[entity.id];
38086         return parentWays && parentWays.length > 1;
38087     },
38088
38089
38090     parentRelations: function(entity) {
38091         var parents = this._parentRels[entity.id],
38092             result = [];
38093
38094         if (parents) {
38095             for (var i = 0; i < parents.length; i++) {
38096                 result.push(this.entity(parents[i]));
38097             }
38098         }
38099         return result;
38100     },
38101
38102
38103     childNodes: function(entity) {
38104         if (this._childNodes[entity.id]) return this._childNodes[entity.id];
38105         if (!entity.nodes) return [];
38106
38107         var nodes = [];
38108         for (var i = 0; i < entity.nodes.length; i++) {
38109             nodes[i] = this.entity(entity.nodes[i]);
38110         }
38111
38112         if (debug) Object.freeze(nodes);
38113
38114         this._childNodes[entity.id] = nodes;
38115         return this._childNodes[entity.id];
38116     },
38117
38118
38119     base: function() {
38120         return {
38121             'entities': utilGetPrototypeOf(this.entities),
38122             'parentWays': utilGetPrototypeOf(this._parentWays),
38123             'parentRels': utilGetPrototypeOf(this._parentRels)
38124         };
38125     },
38126
38127
38128     // Unlike other graph methods, rebase mutates in place. This is because it
38129     // is used only during the history operation that merges newly downloaded
38130     // data into each state. To external consumers, it should appear as if the
38131     // graph always contained the newly downloaded data.
38132     rebase: function(entities, stack, force) {
38133         var base = this.base(),
38134             i, j, k, id;
38135
38136         for (i = 0; i < entities.length; i++) {
38137             var entity = entities[i];
38138
38139             if (!entity.visible || (!force && base.entities[entity.id]))
38140                 continue;
38141
38142             // Merging data into the base graph
38143             base.entities[entity.id] = entity;
38144             this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
38145
38146             // Restore provisionally-deleted nodes that are discovered to have an extant parent
38147             if (entity.type === 'way') {
38148                 for (j = 0; j < entity.nodes.length; j++) {
38149                     id = entity.nodes[j];
38150                     for (k = 1; k < stack.length; k++) {
38151                         var ents = stack[k].entities;
38152                         if (ents.hasOwnProperty(id) && ents[id] === undefined) {
38153                             delete ents[id];
38154                         }
38155                     }
38156                 }
38157             }
38158         }
38159
38160         for (i = 0; i < stack.length; i++) {
38161             stack[i]._updateRebased();
38162         }
38163     },
38164
38165
38166     _updateRebased: function() {
38167         var base = this.base(),
38168             i, k, child, id, keys;
38169
38170         keys = Object.keys(this._parentWays);
38171         for (i = 0; i < keys.length; i++) {
38172             child = keys[i];
38173             if (base.parentWays[child]) {
38174                 for (k = 0; k < base.parentWays[child].length; k++) {
38175                     id = base.parentWays[child][k];
38176                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentWays[child], id)) {
38177                         this._parentWays[child].push(id);
38178                     }
38179                 }
38180             }
38181         }
38182
38183         keys = Object.keys(this._parentRels);
38184         for (i = 0; i < keys.length; i++) {
38185             child = keys[i];
38186             if (base.parentRels[child]) {
38187                 for (k = 0; k < base.parentRels[child].length; k++) {
38188                     id = base.parentRels[child][k];
38189                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentRels[child], id)) {
38190                         this._parentRels[child].push(id);
38191                     }
38192                 }
38193             }
38194         }
38195
38196         this.transients = {};
38197
38198         // this._childNodes is not updated, under the assumption that
38199         // ways are always downloaded with their child nodes.
38200     },
38201
38202
38203     // Updates calculated properties (parentWays, parentRels) for the specified change
38204     _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
38205
38206         parentWays = parentWays || this._parentWays;
38207         parentRels = parentRels || this._parentRels;
38208
38209         var type = entity && entity.type || oldentity && oldentity.type,
38210             removed, added, ways, rels, i;
38211
38212
38213         if (type === 'way') {
38214
38215             // Update parentWays
38216             if (oldentity && entity) {
38217                 removed = lodash.difference(oldentity.nodes, entity.nodes);
38218                 added = lodash.difference(entity.nodes, oldentity.nodes);
38219             } else if (oldentity) {
38220                 removed = oldentity.nodes;
38221                 added = [];
38222             } else if (entity) {
38223                 removed = [];
38224                 added = entity.nodes;
38225             }
38226             for (i = 0; i < removed.length; i++) {
38227                 parentWays[removed[i]] = lodash.without(parentWays[removed[i]], oldentity.id);
38228             }
38229             for (i = 0; i < added.length; i++) {
38230                 ways = lodash.without(parentWays[added[i]], entity.id);
38231                 ways.push(entity.id);
38232                 parentWays[added[i]] = ways;
38233             }
38234
38235         } else if (type === 'relation') {
38236
38237             // Update parentRels
38238             if (oldentity && entity) {
38239                 removed = lodash.difference(oldentity.members, entity.members);
38240                 added = lodash.difference(entity.members, oldentity);
38241             } else if (oldentity) {
38242                 removed = oldentity.members;
38243                 added = [];
38244             } else if (entity) {
38245                 removed = [];
38246                 added = entity.members;
38247             }
38248             for (i = 0; i < removed.length; i++) {
38249                 parentRels[removed[i].id] = lodash.without(parentRels[removed[i].id], oldentity.id);
38250             }
38251             for (i = 0; i < added.length; i++) {
38252                 rels = lodash.without(parentRels[added[i].id], entity.id);
38253                 rels.push(entity.id);
38254                 parentRels[added[i].id] = rels;
38255             }
38256         }
38257     },
38258
38259
38260     replace: function(entity) {
38261         if (this.entities[entity.id] === entity)
38262             return this;
38263
38264         return this.update(function() {
38265             this._updateCalculated(this.entities[entity.id], entity);
38266             this.entities[entity.id] = entity;
38267         });
38268     },
38269
38270
38271     remove: function(entity) {
38272         return this.update(function() {
38273             this._updateCalculated(entity, undefined);
38274             this.entities[entity.id] = undefined;
38275         });
38276     },
38277
38278
38279     revert: function(id) {
38280         var baseEntity = this.base().entities[id],
38281             headEntity = this.entities[id];
38282
38283         if (headEntity === baseEntity)
38284             return this;
38285
38286         return this.update(function() {
38287             this._updateCalculated(headEntity, baseEntity);
38288             delete this.entities[id];
38289         });
38290     },
38291
38292
38293     update: function() {
38294         var graph = this.frozen ? coreGraph$$1(this, true) : this;
38295
38296         for (var i = 0; i < arguments.length; i++) {
38297             arguments[i].call(graph, graph);
38298         }
38299
38300         if (this.frozen) graph.frozen = true;
38301
38302         return graph;
38303     },
38304
38305
38306     // Obliterates any existing entities
38307     load: function(entities) {
38308         var base = this.base();
38309         this.entities = Object.create(base.entities);
38310
38311         for (var i in entities) {
38312             this.entities[i] = entities[i];
38313             this._updateCalculated(base.entities[i], this.entities[i]);
38314         }
38315
38316         return this;
38317     }
38318 };
38319
38320 var index$9 = partialSort;
38321
38322 // Floyd-Rivest selection algorithm:
38323 // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
38324 // The k-th element will have the (k - left + 1)th smallest value in [left, right]
38325
38326 function partialSort(arr, k, left, right, compare) {
38327     left = left || 0;
38328     right = right || (arr.length - 1);
38329     compare = compare || defaultCompare;
38330
38331     while (right > left) {
38332         if (right - left > 600) {
38333             var n = right - left + 1;
38334             var m = k - left + 1;
38335             var z = Math.log(n);
38336             var s = 0.5 * Math.exp(2 * z / 3);
38337             var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
38338             var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
38339             var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
38340             partialSort(arr, k, newLeft, newRight, compare);
38341         }
38342
38343         var t = arr[k];
38344         var i = left;
38345         var j = right;
38346
38347         swap(arr, left, k);
38348         if (compare(arr[right], t) > 0) swap(arr, left, right);
38349
38350         while (i < j) {
38351             swap(arr, i, j);
38352             i++;
38353             j--;
38354             while (compare(arr[i], t) < 0) i++;
38355             while (compare(arr[j], t) > 0) j--;
38356         }
38357
38358         if (compare(arr[left], t) === 0) swap(arr, left, j);
38359         else {
38360             j++;
38361             swap(arr, j, right);
38362         }
38363
38364         if (j <= k) left = j + 1;
38365         if (k <= j) right = j - 1;
38366     }
38367 }
38368
38369 function swap(arr, i, j) {
38370     var tmp = arr[i];
38371     arr[i] = arr[j];
38372     arr[j] = tmp;
38373 }
38374
38375 function defaultCompare(a, b) {
38376     return a < b ? -1 : a > b ? 1 : 0;
38377 }
38378
38379 var index$8 = rbush;
38380
38381 var quickselect = index$9;
38382
38383 function rbush(maxEntries, format) {
38384     if (!(this instanceof rbush)) return new rbush(maxEntries, format);
38385
38386     // max entries in a node is 9 by default; min node fill is 40% for best performance
38387     this._maxEntries = Math.max(4, maxEntries || 9);
38388     this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
38389
38390     if (format) {
38391         this._initFormat(format);
38392     }
38393
38394     this.clear();
38395 }
38396
38397 rbush.prototype = {
38398
38399     all: function () {
38400         return this._all(this.data, []);
38401     },
38402
38403     search: function (bbox) {
38404
38405         var node = this.data,
38406             result = [],
38407             toBBox = this.toBBox;
38408
38409         if (!intersects$1(bbox, node)) return result;
38410
38411         var nodesToSearch = [],
38412             i, len, child, childBBox;
38413
38414         while (node) {
38415             for (i = 0, len = node.children.length; i < len; i++) {
38416
38417                 child = node.children[i];
38418                 childBBox = node.leaf ? toBBox(child) : child;
38419
38420                 if (intersects$1(bbox, childBBox)) {
38421                     if (node.leaf) result.push(child);
38422                     else if (contains$1(bbox, childBBox)) this._all(child, result);
38423                     else nodesToSearch.push(child);
38424                 }
38425             }
38426             node = nodesToSearch.pop();
38427         }
38428
38429         return result;
38430     },
38431
38432     collides: function (bbox) {
38433
38434         var node = this.data,
38435             toBBox = this.toBBox;
38436
38437         if (!intersects$1(bbox, node)) return false;
38438
38439         var nodesToSearch = [],
38440             i, len, child, childBBox;
38441
38442         while (node) {
38443             for (i = 0, len = node.children.length; i < len; i++) {
38444
38445                 child = node.children[i];
38446                 childBBox = node.leaf ? toBBox(child) : child;
38447
38448                 if (intersects$1(bbox, childBBox)) {
38449                     if (node.leaf || contains$1(bbox, childBBox)) return true;
38450                     nodesToSearch.push(child);
38451                 }
38452             }
38453             node = nodesToSearch.pop();
38454         }
38455
38456         return false;
38457     },
38458
38459     load: function (data) {
38460         if (!(data && data.length)) return this;
38461
38462         if (data.length < this._minEntries) {
38463             for (var i = 0, len = data.length; i < len; i++) {
38464                 this.insert(data[i]);
38465             }
38466             return this;
38467         }
38468
38469         // recursively build the tree with the given data from stratch using OMT algorithm
38470         var node = this._build(data.slice(), 0, data.length - 1, 0);
38471
38472         if (!this.data.children.length) {
38473             // save as is if tree is empty
38474             this.data = node;
38475
38476         } else if (this.data.height === node.height) {
38477             // split root if trees have the same height
38478             this._splitRoot(this.data, node);
38479
38480         } else {
38481             if (this.data.height < node.height) {
38482                 // swap trees if inserted one is bigger
38483                 var tmpNode = this.data;
38484                 this.data = node;
38485                 node = tmpNode;
38486             }
38487
38488             // insert the small tree into the large tree at appropriate level
38489             this._insert(node, this.data.height - node.height - 1, true);
38490         }
38491
38492         return this;
38493     },
38494
38495     insert: function (item) {
38496         if (item) this._insert(item, this.data.height - 1);
38497         return this;
38498     },
38499
38500     clear: function () {
38501         this.data = createNode([]);
38502         return this;
38503     },
38504
38505     remove: function (item, equalsFn) {
38506         if (!item) return this;
38507
38508         var node = this.data,
38509             bbox = this.toBBox(item),
38510             path = [],
38511             indexes = [],
38512             i, parent, index, goingUp;
38513
38514         // depth-first iterative tree traversal
38515         while (node || path.length) {
38516
38517             if (!node) { // go up
38518                 node = path.pop();
38519                 parent = path[path.length - 1];
38520                 i = indexes.pop();
38521                 goingUp = true;
38522             }
38523
38524             if (node.leaf) { // check current node
38525                 index = findItem(item, node.children, equalsFn);
38526
38527                 if (index !== -1) {
38528                     // item found, remove the item and condense tree upwards
38529                     node.children.splice(index, 1);
38530                     path.push(node);
38531                     this._condense(path);
38532                     return this;
38533                 }
38534             }
38535
38536             if (!goingUp && !node.leaf && contains$1(node, bbox)) { // go down
38537                 path.push(node);
38538                 indexes.push(i);
38539                 i = 0;
38540                 parent = node;
38541                 node = node.children[0];
38542
38543             } else if (parent) { // go right
38544                 i++;
38545                 node = parent.children[i];
38546                 goingUp = false;
38547
38548             } else node = null; // nothing found
38549         }
38550
38551         return this;
38552     },
38553
38554     toBBox: function (item) { return item; },
38555
38556     compareMinX: compareNodeMinX,
38557     compareMinY: compareNodeMinY,
38558
38559     toJSON: function () { return this.data; },
38560
38561     fromJSON: function (data) {
38562         this.data = data;
38563         return this;
38564     },
38565
38566     _all: function (node, result) {
38567         var nodesToSearch = [];
38568         while (node) {
38569             if (node.leaf) result.push.apply(result, node.children);
38570             else nodesToSearch.push.apply(nodesToSearch, node.children);
38571
38572             node = nodesToSearch.pop();
38573         }
38574         return result;
38575     },
38576
38577     _build: function (items, left, right, height) {
38578
38579         var N = right - left + 1,
38580             M = this._maxEntries,
38581             node;
38582
38583         if (N <= M) {
38584             // reached leaf level; return leaf
38585             node = createNode(items.slice(left, right + 1));
38586             calcBBox(node, this.toBBox);
38587             return node;
38588         }
38589
38590         if (!height) {
38591             // target height of the bulk-loaded tree
38592             height = Math.ceil(Math.log(N) / Math.log(M));
38593
38594             // target number of root entries to maximize storage utilization
38595             M = Math.ceil(N / Math.pow(M, height - 1));
38596         }
38597
38598         node = createNode([]);
38599         node.leaf = false;
38600         node.height = height;
38601
38602         // split the items into M mostly square tiles
38603
38604         var N2 = Math.ceil(N / M),
38605             N1 = N2 * Math.ceil(Math.sqrt(M)),
38606             i, j, right2, right3;
38607
38608         multiSelect(items, left, right, N1, this.compareMinX);
38609
38610         for (i = left; i <= right; i += N1) {
38611
38612             right2 = Math.min(i + N1 - 1, right);
38613
38614             multiSelect(items, i, right2, N2, this.compareMinY);
38615
38616             for (j = i; j <= right2; j += N2) {
38617
38618                 right3 = Math.min(j + N2 - 1, right2);
38619
38620                 // pack each entry recursively
38621                 node.children.push(this._build(items, j, right3, height - 1));
38622             }
38623         }
38624
38625         calcBBox(node, this.toBBox);
38626
38627         return node;
38628     },
38629
38630     _chooseSubtree: function (bbox, node, level, path) {
38631
38632         var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
38633
38634         while (true) {
38635             path.push(node);
38636
38637             if (node.leaf || path.length - 1 === level) break;
38638
38639             minArea = minEnlargement = Infinity;
38640
38641             for (i = 0, len = node.children.length; i < len; i++) {
38642                 child = node.children[i];
38643                 area = bboxArea(child);
38644                 enlargement = enlargedArea(bbox, child) - area;
38645
38646                 // choose entry with the least area enlargement
38647                 if (enlargement < minEnlargement) {
38648                     minEnlargement = enlargement;
38649                     minArea = area < minArea ? area : minArea;
38650                     targetNode = child;
38651
38652                 } else if (enlargement === minEnlargement) {
38653                     // otherwise choose one with the smallest area
38654                     if (area < minArea) {
38655                         minArea = area;
38656                         targetNode = child;
38657                     }
38658                 }
38659             }
38660
38661             node = targetNode || node.children[0];
38662         }
38663
38664         return node;
38665     },
38666
38667     _insert: function (item, level, isNode) {
38668
38669         var toBBox = this.toBBox,
38670             bbox = isNode ? item : toBBox(item),
38671             insertPath = [];
38672
38673         // find the best node for accommodating the item, saving all nodes along the path too
38674         var node = this._chooseSubtree(bbox, this.data, level, insertPath);
38675
38676         // put the item into the node
38677         node.children.push(item);
38678         extend$1(node, bbox);
38679
38680         // split on node overflow; propagate upwards if necessary
38681         while (level >= 0) {
38682             if (insertPath[level].children.length > this._maxEntries) {
38683                 this._split(insertPath, level);
38684                 level--;
38685             } else break;
38686         }
38687
38688         // adjust bboxes along the insertion path
38689         this._adjustParentBBoxes(bbox, insertPath, level);
38690     },
38691
38692     // split overflowed node into two
38693     _split: function (insertPath, level) {
38694
38695         var node = insertPath[level],
38696             M = node.children.length,
38697             m = this._minEntries;
38698
38699         this._chooseSplitAxis(node, m, M);
38700
38701         var splitIndex = this._chooseSplitIndex(node, m, M);
38702
38703         var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
38704         newNode.height = node.height;
38705         newNode.leaf = node.leaf;
38706
38707         calcBBox(node, this.toBBox);
38708         calcBBox(newNode, this.toBBox);
38709
38710         if (level) insertPath[level - 1].children.push(newNode);
38711         else this._splitRoot(node, newNode);
38712     },
38713
38714     _splitRoot: function (node, newNode) {
38715         // split root node
38716         this.data = createNode([node, newNode]);
38717         this.data.height = node.height + 1;
38718         this.data.leaf = false;
38719         calcBBox(this.data, this.toBBox);
38720     },
38721
38722     _chooseSplitIndex: function (node, m, M) {
38723
38724         var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
38725
38726         minOverlap = minArea = Infinity;
38727
38728         for (i = m; i <= M - m; i++) {
38729             bbox1 = distBBox(node, 0, i, this.toBBox);
38730             bbox2 = distBBox(node, i, M, this.toBBox);
38731
38732             overlap = intersectionArea(bbox1, bbox2);
38733             area = bboxArea(bbox1) + bboxArea(bbox2);
38734
38735             // choose distribution with minimum overlap
38736             if (overlap < minOverlap) {
38737                 minOverlap = overlap;
38738                 index = i;
38739
38740                 minArea = area < minArea ? area : minArea;
38741
38742             } else if (overlap === minOverlap) {
38743                 // otherwise choose distribution with minimum area
38744                 if (area < minArea) {
38745                     minArea = area;
38746                     index = i;
38747                 }
38748             }
38749         }
38750
38751         return index;
38752     },
38753
38754     // sorts node children by the best axis for split
38755     _chooseSplitAxis: function (node, m, M) {
38756
38757         var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
38758             compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
38759             xMargin = this._allDistMargin(node, m, M, compareMinX),
38760             yMargin = this._allDistMargin(node, m, M, compareMinY);
38761
38762         // if total distributions margin value is minimal for x, sort by minX,
38763         // otherwise it's already sorted by minY
38764         if (xMargin < yMargin) node.children.sort(compareMinX);
38765     },
38766
38767     // total margin of all possible split distributions where each node is at least m full
38768     _allDistMargin: function (node, m, M, compare) {
38769
38770         node.children.sort(compare);
38771
38772         var toBBox = this.toBBox,
38773             leftBBox = distBBox(node, 0, m, toBBox),
38774             rightBBox = distBBox(node, M - m, M, toBBox),
38775             margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
38776             i, child;
38777
38778         for (i = m; i < M - m; i++) {
38779             child = node.children[i];
38780             extend$1(leftBBox, node.leaf ? toBBox(child) : child);
38781             margin += bboxMargin(leftBBox);
38782         }
38783
38784         for (i = M - m - 1; i >= m; i--) {
38785             child = node.children[i];
38786             extend$1(rightBBox, node.leaf ? toBBox(child) : child);
38787             margin += bboxMargin(rightBBox);
38788         }
38789
38790         return margin;
38791     },
38792
38793     _adjustParentBBoxes: function (bbox, path, level) {
38794         // adjust bboxes along the given tree path
38795         for (var i = level; i >= 0; i--) {
38796             extend$1(path[i], bbox);
38797         }
38798     },
38799
38800     _condense: function (path) {
38801         // go through the path, removing empty nodes and updating bboxes
38802         for (var i = path.length - 1, siblings; i >= 0; i--) {
38803             if (path[i].children.length === 0) {
38804                 if (i > 0) {
38805                     siblings = path[i - 1].children;
38806                     siblings.splice(siblings.indexOf(path[i]), 1);
38807
38808                 } else this.clear();
38809
38810             } else calcBBox(path[i], this.toBBox);
38811         }
38812     },
38813
38814     _initFormat: function (format) {
38815         // data format (minX, minY, maxX, maxY accessors)
38816
38817         // uses eval-type function compilation instead of just accepting a toBBox function
38818         // because the algorithms are very sensitive to sorting functions performance,
38819         // so they should be dead simple and without inner calls
38820
38821         var compareArr = ['return a', ' - b', ';'];
38822
38823         this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
38824         this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
38825
38826         this.toBBox = new Function('a',
38827             'return {minX: a' + format[0] +
38828             ', minY: a' + format[1] +
38829             ', maxX: a' + format[2] +
38830             ', maxY: a' + format[3] + '};');
38831     }
38832 };
38833
38834 function findItem(item, items, equalsFn) {
38835     if (!equalsFn) return items.indexOf(item);
38836
38837     for (var i = 0; i < items.length; i++) {
38838         if (equalsFn(item, items[i])) return i;
38839     }
38840     return -1;
38841 }
38842
38843 // calculate node's bbox from bboxes of its children
38844 function calcBBox(node, toBBox) {
38845     distBBox(node, 0, node.children.length, toBBox, node);
38846 }
38847
38848 // min bounding rectangle of node children from k to p-1
38849 function distBBox(node, k, p, toBBox, destNode) {
38850     if (!destNode) destNode = createNode(null);
38851     destNode.minX = Infinity;
38852     destNode.minY = Infinity;
38853     destNode.maxX = -Infinity;
38854     destNode.maxY = -Infinity;
38855
38856     for (var i = k, child; i < p; i++) {
38857         child = node.children[i];
38858         extend$1(destNode, node.leaf ? toBBox(child) : child);
38859     }
38860
38861     return destNode;
38862 }
38863
38864 function extend$1(a, b) {
38865     a.minX = Math.min(a.minX, b.minX);
38866     a.minY = Math.min(a.minY, b.minY);
38867     a.maxX = Math.max(a.maxX, b.maxX);
38868     a.maxY = Math.max(a.maxY, b.maxY);
38869     return a;
38870 }
38871
38872 function compareNodeMinX(a, b) { return a.minX - b.minX; }
38873 function compareNodeMinY(a, b) { return a.minY - b.minY; }
38874
38875 function bboxArea(a)   { return (a.maxX - a.minX) * (a.maxY - a.minY); }
38876 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
38877
38878 function enlargedArea(a, b) {
38879     return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
38880            (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
38881 }
38882
38883 function intersectionArea(a, b) {
38884     var minX = Math.max(a.minX, b.minX),
38885         minY = Math.max(a.minY, b.minY),
38886         maxX = Math.min(a.maxX, b.maxX),
38887         maxY = Math.min(a.maxY, b.maxY);
38888
38889     return Math.max(0, maxX - minX) *
38890            Math.max(0, maxY - minY);
38891 }
38892
38893 function contains$1(a, b) {
38894     return a.minX <= b.minX &&
38895            a.minY <= b.minY &&
38896            b.maxX <= a.maxX &&
38897            b.maxY <= a.maxY;
38898 }
38899
38900 function intersects$1(a, b) {
38901     return b.minX <= a.maxX &&
38902            b.minY <= a.maxY &&
38903            b.maxX >= a.minX &&
38904            b.maxY >= a.minY;
38905 }
38906
38907 function createNode(children) {
38908     return {
38909         children: children,
38910         height: 1,
38911         leaf: true,
38912         minX: Infinity,
38913         minY: Infinity,
38914         maxX: -Infinity,
38915         maxY: -Infinity
38916     };
38917 }
38918
38919 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
38920 // combines selection algorithm with binary divide & conquer approach
38921
38922 function multiSelect(arr, left, right, n, compare) {
38923     var stack = [left, right],
38924         mid;
38925
38926     while (stack.length) {
38927         right = stack.pop();
38928         left = stack.pop();
38929
38930         if (right - left <= n) continue;
38931
38932         mid = left + Math.ceil((right - left) / n / 2) * n;
38933         quickselect(arr, mid, left, right, compare);
38934
38935         stack.push(left, mid, mid, right);
38936     }
38937 }
38938
38939 function coreTree(head) {
38940     var rtree = index$8(),
38941         bboxes = {},
38942         tree = {};
38943
38944
38945     function entityBBox(entity) {
38946         var bbox = entity.extent(head).bbox();
38947         bbox.id = entity.id;
38948         bboxes[entity.id] = bbox;
38949         return bbox;
38950     }
38951
38952
38953     function updateParents(entity, insertions, memo) {
38954         head.parentWays(entity).forEach(function(way) {
38955             if (bboxes[way.id]) {
38956                 rtree.remove(bboxes[way.id]);
38957                 insertions[way.id] = way;
38958             }
38959             updateParents(way, insertions, memo);
38960         });
38961
38962         head.parentRelations(entity).forEach(function(relation) {
38963             if (memo[entity.id]) return;
38964             memo[entity.id] = true;
38965             if (bboxes[relation.id]) {
38966                 rtree.remove(bboxes[relation.id]);
38967                 insertions[relation.id] = relation;
38968             }
38969             updateParents(relation, insertions, memo);
38970         });
38971     }
38972
38973
38974     tree.rebase = function(entities, force) {
38975         var insertions = {};
38976
38977         for (var i = 0; i < entities.length; i++) {
38978             var entity = entities[i];
38979
38980             if (!entity.visible)
38981                 continue;
38982
38983             if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) {
38984                 if (!force) {
38985                     continue;
38986                 } else if (bboxes[entity.id]) {
38987                     rtree.remove(bboxes[entity.id]);
38988                 }
38989             }
38990
38991             insertions[entity.id] = entity;
38992             updateParents(entity, insertions, {});
38993         }
38994
38995         rtree.load(lodash.map(insertions, entityBBox));
38996
38997         return tree;
38998     };
38999
39000
39001     tree.intersects = function(extent, graph) {
39002         if (graph !== head) {
39003             var diff = coreDifference(head, graph),
39004                 insertions = {};
39005
39006             head = graph;
39007
39008             diff.deleted().forEach(function(entity) {
39009                 rtree.remove(bboxes[entity.id]);
39010                 delete bboxes[entity.id];
39011             });
39012
39013             diff.modified().forEach(function(entity) {
39014                 rtree.remove(bboxes[entity.id]);
39015                 insertions[entity.id] = entity;
39016                 updateParents(entity, insertions, {});
39017             });
39018
39019             diff.created().forEach(function(entity) {
39020                 insertions[entity.id] = entity;
39021             });
39022
39023             rtree.load(lodash.map(insertions, entityBBox));
39024         }
39025
39026         return rtree.search(extent.bbox()).map(function(bbox) {
39027             return head.entity(bbox.id);
39028         });
39029     };
39030
39031
39032     return tree;
39033 }
39034
39035 /*
39036  * This code is licensed under the MIT license.
39037  *
39038  * Copyright © 2013, iD authors.
39039  *
39040  * Portions copyright © 2011, Keith Cirkel
39041  * See https://github.com/keithamus/jwerty
39042  *
39043  */
39044 function d3keybinding(namespace$$1) {
39045     var bindings = [];
39046
39047     function matches(binding, event$$1) {
39048         for (var p in binding.event) {
39049             if (event$$1[p] !== binding.event[p])
39050                 return false;
39051         }
39052         return true;
39053     }
39054
39055     function testBindings(isCapturing) {
39056         for (var i = 0; i < bindings.length; i++) {
39057             var binding = bindings[i];
39058
39059             if (!!binding.capture === isCapturing && matches(binding, event)) {
39060                 binding.callback();
39061             }
39062         }
39063     }
39064
39065     function capture() {
39066         testBindings(true);
39067     }
39068
39069     function bubble() {
39070         var tagName = select(event.target).node().tagName;
39071         if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
39072             return;
39073         }
39074         testBindings(false);
39075     }
39076
39077     function keybinding(selection$$1) {
39078         selection$$1 = selection$$1 || select(document);
39079         selection$$1.on('keydown.capture' + namespace$$1, capture, true);
39080         selection$$1.on('keydown.bubble' + namespace$$1, bubble, false);
39081         return keybinding;
39082     }
39083
39084     keybinding.off = function(selection$$1) {
39085         bindings = [];
39086         selection$$1 = selection$$1 || select(document);
39087         selection$$1.on('keydown.capture' + namespace$$1, null);
39088         selection$$1.on('keydown.bubble' + namespace$$1, null);
39089         return keybinding;
39090     };
39091
39092     keybinding.on = function(codes, callback, capture) {
39093         var arr = [].concat(codes);
39094         for (var i = 0; i < arr.length; i++) {
39095             var code = arr[i];
39096             var binding = {
39097                 event: {
39098                     keyCode: 0,
39099                     shiftKey: false,
39100                     ctrlKey: false,
39101                     altKey: false,
39102                     metaKey: false
39103                 },
39104                 capture: capture,
39105                 callback: callback
39106             };
39107
39108             code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
39109
39110             for (var j = 0; j < code.length; j++) {
39111                 // Normalise matching errors
39112                 if (code[j] === '++') code[i] = '+';
39113
39114                 if (code[j] in d3keybinding.modifierCodes) {
39115                     binding.event[d3keybinding.modifierProperties[d3keybinding.modifierCodes[code[j]]]] = true;
39116                 } else if (code[j] in d3keybinding.keyCodes) {
39117                     binding.event.keyCode = d3keybinding.keyCodes[code[j]];
39118                 }
39119             }
39120
39121             bindings.push(binding);
39122         }
39123
39124         return keybinding;
39125     };
39126
39127     return keybinding;
39128 }
39129
39130
39131 d3keybinding.modifierCodes = {
39132     // Shift key, ⇧
39133     '⇧': 16, shift: 16,
39134     // CTRL key, on Mac: ⌃
39135     '⌃': 17, ctrl: 17,
39136     // ALT key, on Mac: ⌥ (Alt)
39137     '⌥': 18, alt: 18, option: 18,
39138     // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
39139     '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
39140 };
39141
39142 d3keybinding.modifierProperties = {
39143     16: 'shiftKey',
39144     17: 'ctrlKey',
39145     18: 'altKey',
39146     91: 'metaKey'
39147 };
39148
39149 d3keybinding.keyCodes = {
39150     // Backspace key, on Mac: ⌫ (Backspace)
39151     '⌫': 8, backspace: 8,
39152     // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
39153     '⇥': 9, '⇆': 9, tab: 9,
39154     // Return key, ↩
39155     '↩': 13, 'return': 13, enter: 13, '⌅': 13,
39156     // Pause/Break key
39157     'pause': 19, 'pause-break': 19,
39158     // Caps Lock key, ⇪
39159     '⇪': 20, caps: 20, 'caps-lock': 20,
39160     // Escape key, on Mac: ⎋, on Windows: Esc
39161     '⎋': 27, escape: 27, esc: 27,
39162     // Space key
39163     space: 32,
39164     // Page-Up key, or pgup, on Mac: ↖
39165     '↖': 33, pgup: 33, 'page-up': 33,
39166     // Page-Down key, or pgdown, on Mac: ↘
39167     '↘': 34, pgdown: 34, 'page-down': 34,
39168     // END key, on Mac: ⇟
39169     '⇟': 35, end: 35,
39170     // HOME key, on Mac: ⇞
39171     '⇞': 36, home: 36,
39172     // Insert key, or ins
39173     ins: 45, insert: 45,
39174     // Delete key, on Mac: ⌦ (Delete)
39175     '⌦': 46, del: 46, 'delete': 46,
39176     // Left Arrow Key, or ←
39177     '←': 37, left: 37, 'arrow-left': 37,
39178     // Up Arrow Key, or ↑
39179     '↑': 38, up: 38, 'arrow-up': 38,
39180     // Right Arrow Key, or →
39181     '→': 39, right: 39, 'arrow-right': 39,
39182     // Up Arrow Key, or ↓
39183     '↓': 40, down: 40, 'arrow-down': 40,
39184     // odities, printing characters that come out wrong:
39185     // Firefox Equals
39186     'ffequals': 61,
39187     // Num-Multiply, or *
39188     '*': 106, star: 106, asterisk: 106, multiply: 106,
39189     // Num-Plus or +
39190     '+': 107, 'plus': 107,
39191     // Num-Subtract, or -
39192     '-': 109, subtract: 109,
39193     // Firefox Plus
39194     'ffplus': 171,
39195     // Firefox Minus
39196     'ffminus': 173,
39197     // Semicolon
39198     ';': 186, semicolon: 186,
39199     // = or equals
39200     '=': 187, 'equals': 187,
39201     // Comma, or ,
39202     ',': 188, comma: 188,
39203     // Dash / Underscore key
39204     'dash': 189,
39205     // Period, or ., or full-stop
39206     '.': 190, period: 190, 'full-stop': 190,
39207     // Slash, or /, or forward-slash
39208     '/': 191, slash: 191, 'forward-slash': 191,
39209     // Tick, or `, or back-quote
39210     '`': 192, tick: 192, 'back-quote': 192,
39211     // Open bracket, or [
39212     '[': 219, 'open-bracket': 219,
39213     // Back slash, or \
39214     '\\': 220, 'back-slash': 220,
39215     // Close backet, or ]
39216     ']': 221, 'close-bracket': 221,
39217     // Apostrophe, or Quote, or '
39218     '\'': 222, quote: 222, apostrophe: 222
39219 };
39220
39221 // NUMPAD 0-9
39222 var i$1 = 95;
39223 var n = 0;
39224 while (++i$1 < 106) {
39225     d3keybinding.keyCodes['num-' + n] = i$1;
39226     ++n;
39227 }
39228
39229 // 0-9
39230 i$1 = 47; n = 0;
39231 while (++i$1 < 58) {
39232     d3keybinding.keyCodes[n] = i$1;
39233     ++n;
39234 }
39235
39236 // F1-F25
39237 i$1 = 111; n = 1;
39238 while (++i$1 < 136) {
39239     d3keybinding.keyCodes['f' + n] = i$1;
39240     ++n;
39241 }
39242
39243 // a-z
39244 i$1 = 64;
39245 while (++i$1 < 91) {
39246     d3keybinding.keyCodes[String.fromCharCode(i$1).toLowerCase()] = i$1;
39247 }
39248
39249 function tooltip() {
39250   var tooltip = function(selection$$1) {
39251       selection$$1.each(setup);
39252     },
39253     animation = utilFunctor(false),
39254     html$$1 = utilFunctor(false),
39255     title = function() {
39256       var title = this.getAttribute('data-original-title');
39257       if (title) {
39258         return title;
39259       } else {
39260         title = this.getAttribute('title');
39261         this.removeAttribute('title');
39262         this.setAttribute('data-original-title', title);
39263       }
39264       return title;
39265     },
39266     over = 'mouseenter.tooltip',
39267     out = 'mouseleave.tooltip',
39268     placement = utilFunctor('top');
39269
39270
39271   tooltip.title = function(_) {
39272     if (arguments.length) {
39273       title = utilFunctor(_);
39274       return tooltip;
39275     } else {
39276       return title;
39277     }
39278   };
39279
39280
39281   tooltip.html = function(_) {
39282     if (arguments.length) {
39283       html$$1 = utilFunctor(_);
39284       return tooltip;
39285     } else {
39286       return html$$1;
39287     }
39288   };
39289
39290
39291   tooltip.placement = function(_) {
39292     if (arguments.length) {
39293       placement = utilFunctor(_);
39294       return tooltip;
39295     } else {
39296       return placement;
39297     }
39298   };
39299
39300
39301   tooltip.show = function(selection$$1) {
39302     selection$$1.each(show);
39303   };
39304
39305
39306   tooltip.hide = function(selection$$1) {
39307     selection$$1.each(hide);
39308   };
39309
39310
39311   tooltip.toggle = function(selection$$1) {
39312     selection$$1.each(toggle);
39313   };
39314
39315
39316   tooltip.destroy = function(selection$$1) {
39317     selection$$1
39318       .on(over, null)
39319       .on(out, null)
39320       .attr('title', function() {
39321         return this.getAttribute('data-original-title') || this.getAttribute('title');
39322       })
39323       .attr('data-original-title', null)
39324       .selectAll('.tooltip')
39325       .remove();
39326   };
39327
39328
39329   function setup() {
39330     var root = select(this),
39331         animate = animation.apply(this, arguments),
39332         tip = root.selectAll('.tooltip').data([0]);
39333
39334     var enter = tip.enter()
39335       .append('div')
39336       .attr('class', 'tooltip');
39337
39338     enter
39339       .append('div')
39340       .attr('class', 'tooltip-arrow');
39341
39342     enter
39343       .append('div')
39344       .attr('class', 'tooltip-inner');
39345
39346     tip = enter
39347       .merge(tip);
39348
39349     if (animate) {
39350       tip.classed('fade', true);
39351     }
39352
39353     var place = placement.apply(this, arguments);
39354     tip.classed(place, true);
39355
39356     root.on(over, show);
39357     root.on(out, hide);
39358   }
39359
39360
39361   function show() {
39362     var root = select(this),
39363       content = title.apply(this, arguments),
39364       tip = root.selectAll('.tooltip')
39365         .classed('in', true),
39366       markup = html$$1.apply(this, arguments);
39367
39368     tip.selectAll('.tooltip-inner')[markup ? 'html' : 'text'](content);
39369     var place = placement.apply(this, arguments),
39370       outer = getPosition(root.node()),
39371       inner = getPosition(tip.node()),
39372       pos;
39373
39374     switch (place) {
39375       case 'top':
39376         pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
39377         break;
39378       case 'right':
39379         pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
39380         break;
39381       case 'left':
39382         pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
39383         break;
39384       case 'bottom':
39385         pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
39386         break;
39387     }
39388
39389     if (pos) {
39390       tip.style('left', ~~pos.x + 'px').style('top', ~~pos.y + 'px');
39391     } else {
39392       tip.style('left', null).style('top', null);
39393     }
39394
39395     this.tooltipVisible = true;
39396   }
39397
39398
39399   function hide() {
39400     select(this).selectAll('.tooltip')
39401       .classed('in', false);
39402
39403     this.tooltipVisible = false;
39404   }
39405
39406
39407   function toggle() {
39408     if (this.tooltipVisible) {
39409       hide.apply(this, arguments);
39410     } else {
39411       show.apply(this, arguments);
39412     }
39413   }
39414
39415   return tooltip;
39416 }
39417
39418
39419 function getPosition(node) {
39420   var mode = select(node).style('position');
39421   if (mode === 'absolute' || mode === 'static') {
39422     return {
39423       x: node.offsetLeft,
39424       y: node.offsetTop,
39425       w: node.offsetWidth,
39426       h: node.offsetHeight
39427     };
39428   } else {
39429     return {
39430       x: 0,
39431       y: 0,
39432       w: node.offsetWidth,
39433       h: node.offsetHeight
39434     };
39435   }
39436 }
39437
39438 function svgAreas$$1(projection, context) {
39439     // Patterns only work in Firefox when set directly on element.
39440     // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
39441     var patterns = {
39442         wetland: 'wetland',
39443         beach: 'beach',
39444         scrub: 'scrub',
39445         construction: 'construction',
39446         military: 'construction',
39447         cemetery: 'cemetery',
39448         grave_yard: 'cemetery',
39449         meadow: 'meadow',
39450         farm: 'farmland',
39451         farmland: 'farmland',
39452         orchard: 'orchard'
39453     };
39454
39455     var patternKeys = ['landuse', 'natural', 'amenity'];
39456
39457
39458     function setPattern(d) {
39459         for (var i = 0; i < patternKeys.length; i++) {
39460             if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
39461                 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
39462                 return;
39463             }
39464         }
39465         this.style.fill = this.style.stroke = '';
39466     }
39467
39468
39469     return function drawAreas(selection$$1, graph, entities, filter) {
39470         var path$$1 = svgPath(projection, graph, true),
39471             areas = {},
39472             multipolygon;
39473
39474         for (var i = 0; i < entities.length; i++) {
39475             var entity = entities[i];
39476             if (entity.geometry(graph) !== 'area') continue;
39477
39478             multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph);
39479             if (multipolygon) {
39480                 areas[multipolygon.id] = {
39481                     entity: multipolygon.mergeTags(entity.tags),
39482                     area: Math.abs(entity.area(graph))
39483                 };
39484             } else if (!areas[entity.id]) {
39485                 areas[entity.id] = {
39486                     entity: entity,
39487                     area: Math.abs(entity.area(graph))
39488                 };
39489             }
39490         }
39491
39492         areas = values(areas).filter(function hasPath(a) { return path$$1(a.entity); });
39493         areas.sort(function areaSort(a, b) { return b.area - a.area; });
39494         areas = lodash.map(areas, 'entity');
39495
39496         var strokes = areas.filter(function(area$$1) {
39497             return area$$1.type === 'way';
39498         });
39499
39500         var data = {
39501             clip: areas,
39502             shadow: strokes,
39503             stroke: strokes,
39504             fill: areas
39505         };
39506
39507         var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath')
39508            .filter(filter)
39509            .data(data.clip, osmEntity$$1.key);
39510
39511         clipPaths.exit()
39512            .remove();
39513
39514         var clipPathsEnter = clipPaths.enter()
39515            .append('clipPath')
39516            .attr('class', 'clipPath')
39517            .attr('id', function(entity) { return entity.id + '-clippath'; });
39518
39519         clipPathsEnter
39520            .append('path');
39521
39522         clipPaths.merge(clipPathsEnter)
39523            .selectAll('path')
39524            .attr('d', path$$1);
39525
39526
39527         var layer = selection$$1.selectAll('.layer-areas');
39528
39529         var areagroup = layer
39530             .selectAll('g.areagroup')
39531             .data(['fill', 'shadow', 'stroke']);
39532
39533         areagroup = areagroup.enter()
39534             .append('g')
39535             .attr('class', function(d) { return 'areagroup area-' + d; })
39536             .merge(areagroup);
39537
39538         var paths = areagroup
39539             .selectAll('path')
39540             .filter(filter)
39541             .data(function(layer) { return data[layer]; }, osmEntity$$1.key);
39542
39543         paths.exit()
39544             .remove();
39545
39546         var fills = selection$$1.selectAll('.area-fill path.area').nodes();
39547
39548         var bisect$$1 = bisector(function(node) {
39549             return -node.__data__.area(graph);
39550         }).left;
39551
39552         function sortedByArea(entity) {
39553             if (this._parent.__data__ === 'fill') {
39554                 return fills[bisect$$1(fills, -entity.area(graph))];
39555             }
39556         }
39557
39558         paths = paths.enter()
39559             .insert('path', sortedByArea)
39560             .merge(paths)
39561             .each(function(entity) {
39562                 var layer = this.parentNode.__data__;
39563
39564                 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
39565
39566                 if (layer === 'fill') {
39567                     this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
39568                     setPattern.apply(this, arguments);
39569                 }
39570             })
39571             .call(svgTagClasses())
39572             .attr('d', path$$1);
39573     };
39574 }
39575
39576 function svgDebug(projection, context) {
39577
39578     function multipolygons(imagery) {
39579         return imagery.map(function(data$$1) {
39580             return {
39581                 type: 'MultiPolygon',
39582                 coordinates: [ data$$1.polygon ]
39583             };
39584         });
39585     }
39586
39587     function drawDebug(selection$$1) {
39588         var showsTile = context.getDebug('tile'),
39589             showsCollision = context.getDebug('collision'),
39590             showsImagery = context.getDebug('imagery'),
39591             showsImperial = context.getDebug('imperial'),
39592             showsDriveLeft = context.getDebug('driveLeft'),
39593             path$$1 = index$5(projection);
39594
39595
39596         var debugData = [];
39597         if (showsTile) {
39598             debugData.push({ class: 'red', label: 'tile' });
39599         }
39600         if (showsCollision) {
39601             debugData.push({ class: 'yellow', label: 'collision' });
39602         }
39603         if (showsImagery) {
39604             debugData.push({ class: 'orange', label: 'imagery' });
39605         }
39606         if (showsImperial) {
39607             debugData.push({ class: 'cyan', label: 'imperial' });
39608         }
39609         if (showsDriveLeft) {
39610             debugData.push({ class: 'green', label: 'driveLeft' });
39611         }
39612
39613
39614         var legend = select('#content')
39615             .selectAll('.debug-legend')
39616             .data(debugData.length ? [0] : []);
39617
39618         legend.exit()
39619             .remove();
39620
39621         legend = legend.enter()
39622             .append('div')
39623             .attr('class', 'fillD debug-legend')
39624             .merge(legend);
39625
39626
39627         var legendItems = legend.selectAll('.debug-legend-item')
39628             .data(debugData, function(d) { return d.label; });
39629
39630         legendItems.exit()
39631             .remove();
39632
39633         legendItems.enter()
39634             .append('span')
39635             .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
39636             .text(function(d) { return d.label; });
39637
39638
39639         var layer = selection$$1.selectAll('.layer-debug')
39640             .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
39641
39642         layer.exit()
39643             .remove();
39644
39645         layer = layer.enter()
39646             .append('g')
39647             .attr('class', 'layer-debug')
39648             .merge(layer);
39649
39650
39651         var extent$$1 = context.map().extent(),
39652             dataImagery = data.imagery || [],
39653             availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) {
39654                 if (!source.polygon) return false;
39655                 return source.polygon.some(function(polygon) {
39656                     return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
39657                 });
39658             }));
39659
39660         var imagery = layer.selectAll('path.debug-imagery')
39661             .data(showsImagery ? availableImagery : []);
39662
39663         imagery.exit()
39664             .remove();
39665
39666         imagery.enter()
39667             .append('path')
39668             .attr('class', 'debug-imagery debug orange');
39669
39670
39671         var imperial = layer
39672             .selectAll('path.debug-imperial')
39673             .data(showsImperial ? [dataImperial] : []);
39674
39675         imperial.exit()
39676             .remove();
39677
39678         imperial.enter()
39679             .append('path')
39680             .attr('class', 'debug-imperial debug cyan');
39681
39682
39683         var driveLeft = layer
39684             .selectAll('path.debug-drive-left')
39685             .data(showsDriveLeft ? [dataDriveLeft] : []);
39686
39687         driveLeft.exit()
39688             .remove();
39689
39690         driveLeft.enter()
39691             .append('path')
39692             .attr('class', 'debug-drive-left debug green');
39693
39694
39695         // update
39696         layer.selectAll('path')
39697             .attr('d', path$$1);
39698     }
39699
39700
39701     // This looks strange because `enabled` methods on other layers are
39702     // chainable getter/setters, and this one is just a getter.
39703     drawDebug.enabled = function() {
39704         if (!arguments.length) {
39705             return context.getDebug('tile') ||
39706                 context.getDebug('collision') ||
39707                 context.getDebug('imagery') ||
39708                 context.getDebug('imperial') ||
39709                 context.getDebug('driveLeft');
39710         } else {
39711             return this;
39712         }
39713     };
39714
39715
39716     return drawDebug;
39717 }
39718
39719 /*
39720     A standalone SVG element that contains only a `defs` sub-element. To be
39721     used once globally, since defs IDs must be unique within a document.
39722 */
39723 function svgDefs(context) {
39724
39725     function SVGSpriteDefinition(id, href) {
39726         return function(defs) {
39727             request(href)
39728                 .mimeType('image/svg+xml')
39729                 .response(function(xhr) { return xhr.responseXML; })
39730                 .get(function(err, svg) {
39731                     if (err) return;
39732                     defs.node().appendChild(
39733                         select(svg.documentElement).attr('id', id).node()
39734                     );
39735                 });
39736         };
39737     }
39738
39739
39740     return function drawDefs(selection$$1) {
39741         var defs = selection$$1.append('defs');
39742
39743         // marker
39744         defs.append('marker')
39745             .attr('id', 'oneway-marker')
39746             .attr('viewBox', '0 0 10 10')
39747             .attr('refY', 2.5)
39748             .attr('refX', 5)
39749             .attr('markerWidth', 2)
39750             .attr('markerHeight', 2)
39751             .attr('markerUnits', 'strokeWidth')
39752             .attr('orient', 'auto')
39753
39754             .append('path')
39755             .attr('class', 'oneway')
39756             .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')
39757             .attr('stroke', 'none')
39758             .attr('fill', '#000')
39759             .attr('opacity', '0.5');
39760
39761         // patterns
39762         var patterns = defs.selectAll('pattern')
39763             .data([
39764                 // pattern name, pattern image name
39765                 ['wetland', 'wetland'],
39766                 ['construction', 'construction'],
39767                 ['cemetery', 'cemetery'],
39768                 ['orchard', 'orchard'],
39769                 ['farmland', 'farmland'],
39770                 ['beach', 'dots'],
39771                 ['scrub', 'dots'],
39772                 ['meadow', 'dots']
39773             ])
39774             .enter()
39775             .append('pattern')
39776             .attr('id', function (d) {
39777                 return 'pattern-' + d[0];
39778             })
39779             .attr('width', 32)
39780             .attr('height', 32)
39781             .attr('patternUnits', 'userSpaceOnUse');
39782
39783         patterns.append('rect')
39784             .attr('x', 0)
39785             .attr('y', 0)
39786             .attr('width', 32)
39787             .attr('height', 32)
39788             .attr('class', function (d) {
39789                     return 'pattern-color-' + d[0];
39790             });
39791
39792         patterns.append('image')
39793             .attr('x', 0)
39794             .attr('y', 0)
39795             .attr('width', 32)
39796             .attr('height', 32)
39797             .attr('xlink:href', function (d) {
39798                 return context.imagePath('pattern/' + d[1] + '.png');
39799             });
39800
39801         // clip paths
39802         defs.selectAll()
39803             .data([12, 18, 20, 32, 45])
39804             .enter()
39805             .append('clipPath')
39806             .attr('id', function (d) {
39807                 return 'clip-square-' + d;
39808             })
39809             .append('rect')
39810             .attr('x', 0)
39811             .attr('y', 0)
39812             .attr('width', function (d) {
39813                 return d;
39814             })
39815             .attr('height', function (d) {
39816                 return d;
39817             });
39818
39819         defs.call(SVGSpriteDefinition(
39820             'iD-sprite',
39821             context.imagePath('iD-sprite.svg')));
39822
39823         defs.call(SVGSpriteDefinition(
39824             'maki-sprite',
39825             context.imagePath('maki-sprite.svg')));
39826     };
39827 }
39828
39829 var sax = createCommonjsModule(function (module, exports) {
39830 //[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]
39831 //[4a]          NameChar           ::=          NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
39832 //[5]           Name       ::=          NameStartChar (NameChar)*
39833 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
39834 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\u203F-\u2040]");
39835 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
39836 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
39837 //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(',')
39838
39839 //S_TAG,        S_ATTR, S_EQ,   S_V
39840 //S_ATTR_S,     S_E,    S_S,    S_C
39841 var S_TAG = 0;//tag name offerring
39842 var S_ATTR = 1;//attr name offerring 
39843 var S_ATTR_S=2;//attr name end and space offer
39844 var S_EQ = 3;//=space?
39845 var S_V = 4;//attr value(no quot value only)
39846 var S_E = 5;//attr value end and no space(quot end)
39847 var S_S = 6;//(attr value end || tag end ) && (space offer)
39848 var S_C = 7;//closed el<el />
39849
39850 function XMLReader(){
39851         
39852 }
39853
39854 XMLReader.prototype = {
39855         parse:function(source,defaultNSMap,entityMap){
39856                 var domBuilder = this.domBuilder;
39857                 domBuilder.startDocument();
39858                 _copy(defaultNSMap ,defaultNSMap = {});
39859                 parse(source,defaultNSMap,entityMap,
39860                                 domBuilder,this.errorHandler);
39861                 domBuilder.endDocument();
39862         }
39863 };
39864 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
39865   function fixedFromCharCode(code) {
39866                 // String.prototype.fromCharCode does not supports
39867                 // > 2 bytes unicode chars directly
39868                 if (code > 0xffff) {
39869                         code -= 0x10000;
39870                         var surrogate1 = 0xd800 + (code >> 10)
39871                                 , surrogate2 = 0xdc00 + (code & 0x3ff);
39872
39873                         return String.fromCharCode(surrogate1, surrogate2);
39874                 } else {
39875                         return String.fromCharCode(code);
39876                 }
39877         }
39878         function entityReplacer(a){
39879                 var k = a.slice(1,-1);
39880                 if(k in entityMap){
39881                         return entityMap[k]; 
39882                 }else if(k.charAt(0) === '#'){
39883                         return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
39884                 }else{
39885                         errorHandler.error('entity not found:'+a);
39886                         return a;
39887                 }
39888         }
39889         function appendText(end){//has some bugs
39890                 if(end>start){
39891                         var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
39892                         locator&&position(start);
39893                         domBuilder.characters(xt,0,end-start);
39894                         start = end;
39895                 }
39896         }
39897         function position(p,m){
39898                 while(p>=lineEnd && (m = linePattern.exec(source))){
39899                         lineStart = m.index;
39900                         lineEnd = lineStart + m[0].length;
39901                         locator.lineNumber++;
39902                         //console.log('line++:',locator,startPos,endPos)
39903                 }
39904                 locator.columnNumber = p-lineStart+1;
39905         }
39906         var lineStart = 0;
39907         var lineEnd = 0;
39908         var linePattern = /.+(?:\r\n?|\n)|.*$/g;
39909         var locator = domBuilder.locator;
39910         
39911         var parseStack = [{currentNSMap:defaultNSMapCopy}];
39912         var closeMap = {};
39913         var start = 0;
39914         while(true){
39915                 try{
39916                         var tagStart = source.indexOf('<',start);
39917                         if(tagStart<0){
39918                                 if(!source.substr(start).match(/^\s*$/)){
39919                                         var doc = domBuilder.document;
39920                                 var text = doc.createTextNode(source.substr(start));
39921                                 doc.appendChild(text);
39922                                 domBuilder.currentElement = text;
39923                                 }
39924                                 return;
39925                         }
39926                         if(tagStart>start){
39927                                 appendText(tagStart);
39928                         }
39929                         switch(source.charAt(tagStart+1)){
39930                         case '/':
39931                                 var end = source.indexOf('>',tagStart+3);
39932                                 var tagName = source.substring(tagStart+2,end);
39933                                 var config = parseStack.pop();
39934                                 var localNSMap = config.localNSMap;
39935                         if(config.tagName != tagName){
39936                             errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
39937                         }
39938                                 domBuilder.endElement(config.uri,config.localName,tagName);
39939                                 if(localNSMap){
39940                                         for(var prefix in localNSMap){
39941                                                 domBuilder.endPrefixMapping(prefix) ;
39942                                         }
39943                                 }
39944                                 end++;
39945                                 break;
39946                                 // end elment
39947                         case '?':// <?...?>
39948                                 locator&&position(tagStart);
39949                                 end = parseInstruction(source,tagStart,domBuilder);
39950                                 break;
39951                         case '!':// <!doctype,<![CDATA,<!--
39952                                 locator&&position(tagStart);
39953                                 end = parseDCC(source,tagStart,domBuilder,errorHandler);
39954                                 break;
39955                         default:
39956                         
39957                                 locator&&position(tagStart);
39958                                 
39959                                 var el = new ElementAttributes();
39960                                 
39961                                 //elStartEnd
39962                                 var end = parseElementStartPart(source,tagStart,el,entityReplacer,errorHandler);
39963                                 var len = el.length;
39964                                 
39965                                 if(locator){
39966                                         if(len){
39967                                                 //attribute position fixed
39968                                                 for(var i = 0;i<len;i++){
39969                                                         var a = el[i];
39970                                                         position(a.offset);
39971                                                         a.offset = copyLocator(locator,{});
39972                                                 }
39973                                         }
39974                                         position(end);
39975                                 }
39976                                 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
39977                                         el.closed = true;
39978                                         if(!entityMap.nbsp){
39979                                                 errorHandler.warning('unclosed xml attribute');
39980                                         }
39981                                 }
39982                                 appendElement(el,domBuilder,parseStack);
39983                                 
39984                                 
39985                                 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
39986                                         end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
39987                                 }else{
39988                                         end++;
39989                                 }
39990                         }
39991                 }catch(e){
39992                         errorHandler.error('element parse error: '+e);
39993                         end = -1;
39994                 }
39995                 if(end>start){
39996                         start = end;
39997                 }else{
39998                         //TODO: 这里有可能sax回退,有位置错误风险
39999                         appendText(Math.max(tagStart,start)+1);
40000                 }
40001         }
40002 }
40003 function copyLocator(f,t){
40004         t.lineNumber = f.lineNumber;
40005         t.columnNumber = f.columnNumber;
40006         return t;
40007 }
40008
40009 /**
40010  * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
40011  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40012  */
40013 function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
40014         var attrName;
40015         var value;
40016         var p = ++start;
40017         var s = S_TAG;//status
40018         while(true){
40019                 var c = source.charAt(p);
40020                 switch(c){
40021                 case '=':
40022                         if(s === S_ATTR){//attrName
40023                                 attrName = source.slice(start,p);
40024                                 s = S_EQ;
40025                         }else if(s === S_ATTR_S){
40026                                 s = S_EQ;
40027                         }else{
40028                                 //fatalError: equal must after attrName or space after attrName
40029                                 throw new Error('attribute equal must after attrName');
40030                         }
40031                         break;
40032                 case '\'':
40033                 case '"':
40034                         if(s === S_EQ){//equal
40035                                 start = p+1;
40036                                 p = source.indexOf(c,start);
40037                                 if(p>0){
40038                                         value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40039                                         el.add(attrName,value,start-1);
40040                                         s = S_E;
40041                                 }else{
40042                                         //fatalError: no end quot match
40043                                         throw new Error('attribute value no end \''+c+'\' match');
40044                                 }
40045                         }else if(s == S_V){
40046                                 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40047                                 //console.log(attrName,value,start,p)
40048                                 el.add(attrName,value,start);
40049                                 //console.dir(el)
40050                                 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
40051                                 start = p+1;
40052                                 s = S_E;
40053                         }else{
40054                                 //fatalError: no equal before
40055                                 throw new Error('attribute value must after "="');
40056                         }
40057                         break;
40058                 case '/':
40059                         switch(s){
40060                         case S_TAG:
40061                                 el.setTagName(source.slice(start,p));
40062                         case S_E:
40063                         case S_S:
40064                         case S_C:
40065                                 s = S_C;
40066                                 el.closed = true;
40067                         case S_V:
40068                         case S_ATTR:
40069                         case S_ATTR_S:
40070                                 break;
40071                         //case S_EQ:
40072                         default:
40073                                 throw new Error("attribute invalid close char('/')")
40074                         }
40075                         break;
40076                 case ''://end document
40077                         //throw new Error('unexpected end of input')
40078                         errorHandler.error('unexpected end of input');
40079                 case '>':
40080                         switch(s){
40081                         case S_TAG:
40082                                 el.setTagName(source.slice(start,p));
40083                         case S_E:
40084                         case S_S:
40085                         case S_C:
40086                                 break;//normal
40087                         case S_V://Compatible state
40088                         case S_ATTR:
40089                                 value = source.slice(start,p);
40090                                 if(value.slice(-1) === '/'){
40091                                         el.closed  = true;
40092                                         value = value.slice(0,-1);
40093                                 }
40094                         case S_ATTR_S:
40095                                 if(s === S_ATTR_S){
40096                                         value = attrName;
40097                                 }
40098                                 if(s == S_V){
40099                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40100                                         el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start);
40101                                 }else{
40102                                         errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
40103                                         el.add(value,value,start);
40104                                 }
40105                                 break;
40106                         case S_EQ:
40107                                 throw new Error('attribute value missed!!');
40108                         }
40109 //                      console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
40110                         return p;
40111                 /*xml space '\x20' | #x9 | #xD | #xA; */
40112                 case '\u0080':
40113                         c = ' ';
40114                 default:
40115                         if(c<= ' '){//space
40116                                 switch(s){
40117                                 case S_TAG:
40118                                         el.setTagName(source.slice(start,p));//tagName
40119                                         s = S_S;
40120                                         break;
40121                                 case S_ATTR:
40122                                         attrName = source.slice(start,p);
40123                                         s = S_ATTR_S;
40124                                         break;
40125                                 case S_V:
40126                                         var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40127                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40128                                         el.add(attrName,value,start);
40129                                 case S_E:
40130                                         s = S_S;
40131                                         break;
40132                                 //case S_S:
40133                                 //case S_EQ:
40134                                 //case S_ATTR_S:
40135                                 //      void();break;
40136                                 //case S_C:
40137                                         //ignore warning
40138                                 }
40139                         }else{//not space
40140 //S_TAG,        S_ATTR, S_EQ,   S_V
40141 //S_ATTR_S,     S_E,    S_S,    S_C
40142                                 switch(s){
40143                                 //case S_TAG:void();break;
40144                                 //case S_ATTR:void();break;
40145                                 //case S_V:void();break;
40146                                 case S_ATTR_S:
40147                                         errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!');
40148                                         el.add(attrName,attrName,start);
40149                                         start = p;
40150                                         s = S_ATTR;
40151                                         break;
40152                                 case S_E:
40153                                         errorHandler.warning('attribute space is required"'+attrName+'"!!');
40154                                 case S_S:
40155                                         s = S_ATTR;
40156                                         start = p;
40157                                         break;
40158                                 case S_EQ:
40159                                         s = S_V;
40160                                         start = p;
40161                                         break;
40162                                 case S_C:
40163                                         throw new Error("elements closed character '/' and '>' must be connected to");
40164                                 }
40165                         }
40166                 }
40167                 p++;
40168         }
40169 }
40170 /**
40171  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40172  */
40173 function appendElement(el,domBuilder,parseStack){
40174         var tagName = el.tagName;
40175         var localNSMap = null;
40176         var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40177         var i = el.length;
40178         while(i--){
40179                 var a = el[i];
40180                 var qName = a.qName;
40181                 var value = a.value;
40182                 var nsp = qName.indexOf(':');
40183                 if(nsp>0){
40184                         var prefix = a.prefix = qName.slice(0,nsp);
40185                         var localName = qName.slice(nsp+1);
40186                         var nsPrefix = prefix === 'xmlns' && localName;
40187                 }else{
40188                         localName = qName;
40189                         prefix = null;
40190                         nsPrefix = qName === 'xmlns' && '';
40191                 }
40192                 //can not set prefix,because prefix !== ''
40193                 a.localName = localName ;
40194                 //prefix == null for no ns prefix attribute 
40195                 if(nsPrefix !== false){//hack!!
40196                         if(localNSMap == null){
40197                                 localNSMap = {};
40198                                 //console.log(currentNSMap,0)
40199                                 _copy(currentNSMap,currentNSMap={});
40200                                 //console.log(currentNSMap,1)
40201                         }
40202                         currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
40203                         a.uri = 'http://www.w3.org/2000/xmlns/';
40204                         domBuilder.startPrefixMapping(nsPrefix, value); 
40205                 }
40206         }
40207         var i = el.length;
40208         while(i--){
40209                 a = el[i];
40210                 var prefix = a.prefix;
40211                 if(prefix){//no prefix attribute has no namespace
40212                         if(prefix === 'xml'){
40213                                 a.uri = 'http://www.w3.org/XML/1998/namespace';
40214                         }if(prefix !== 'xmlns'){
40215                                 a.uri = currentNSMap[prefix];
40216                                 
40217                                 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
40218                         }
40219                 }
40220         }
40221         var nsp = tagName.indexOf(':');
40222         if(nsp>0){
40223                 prefix = el.prefix = tagName.slice(0,nsp);
40224                 localName = el.localName = tagName.slice(nsp+1);
40225         }else{
40226                 prefix = null;//important!!
40227                 localName = el.localName = tagName;
40228         }
40229         //no prefix element has default namespace
40230         var ns = el.uri = currentNSMap[prefix || ''];
40231         domBuilder.startElement(ns,localName,tagName,el);
40232         //endPrefixMapping and startPrefixMapping have not any help for dom builder
40233         //localNSMap = null
40234         if(el.closed){
40235                 domBuilder.endElement(ns,localName,tagName);
40236                 if(localNSMap){
40237                         for(prefix in localNSMap){
40238                                 domBuilder.endPrefixMapping(prefix); 
40239                         }
40240                 }
40241         }else{
40242                 el.currentNSMap = currentNSMap;
40243                 el.localNSMap = localNSMap;
40244                 parseStack.push(el);
40245         }
40246 }
40247 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
40248         if(/^(?:script|textarea)$/i.test(tagName)){
40249                 var elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);
40250                 var text = source.substring(elStartEnd+1,elEndStart);
40251                 if(/[&<]/.test(text)){
40252                         if(/^script$/i.test(tagName)){
40253                                 //if(!/\]\]>/.test(text)){
40254                                         //lexHandler.startCDATA();
40255                                         domBuilder.characters(text,0,text.length);
40256                                         //lexHandler.endCDATA();
40257                                         return elEndStart;
40258                                 //}
40259                         }//}else{//text area
40260                                 text = text.replace(/&#?\w+;/g,entityReplacer);
40261                                 domBuilder.characters(text,0,text.length);
40262                                 return elEndStart;
40263                         //}
40264                         
40265                 }
40266         }
40267         return elStartEnd+1;
40268 }
40269 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
40270         //if(tagName in closeMap){
40271         var pos = closeMap[tagName];
40272         if(pos == null){
40273                 //console.log(tagName)
40274                 pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>');
40275         }
40276         return pos<elStartEnd;
40277         //} 
40278 }
40279 function _copy(source,target){
40280         for(var n in source){target[n] = source[n];}
40281 }
40282 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
40283         var next= source.charAt(start+2);
40284         switch(next){
40285         case '-':
40286                 if(source.charAt(start + 3) === '-'){
40287                         var end = source.indexOf('-->',start+4);
40288                         //append comment source.substring(4,end)//<!--
40289                         if(end>start){
40290                                 domBuilder.comment(source,start+4,end-start-4);
40291                                 return end+3;
40292                         }else{
40293                                 errorHandler.error("Unclosed comment");
40294                                 return -1;
40295                         }
40296                 }else{
40297                         //error
40298                         return -1;
40299                 }
40300         default:
40301                 if(source.substr(start+3,6) == 'CDATA['){
40302                         var end = source.indexOf(']]>',start+9);
40303                         domBuilder.startCDATA();
40304                         domBuilder.characters(source,start+9,end-start-9);
40305                         domBuilder.endCDATA(); 
40306                         return end+3;
40307                 }
40308                 //<!DOCTYPE
40309                 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) 
40310                 var matchs = split(source,start);
40311                 var len = matchs.length;
40312                 if(len>1 && /!doctype/i.test(matchs[0][0])){
40313                         var name = matchs[1][0];
40314                         var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
40315                         var sysid = len>4 && matchs[4][0];
40316                         var lastMatch = matchs[len-1];
40317                         domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
40318                                         sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
40319                         domBuilder.endDTD();
40320                         
40321                         return lastMatch.index+lastMatch[0].length
40322                 }
40323         }
40324         return -1;
40325 }
40326
40327
40328
40329 function parseInstruction(source,start,domBuilder){
40330         var end = source.indexOf('?>',start);
40331         if(end){
40332                 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
40333                 if(match){
40334                         var len = match[0].length;
40335                         domBuilder.processingInstruction(match[1], match[2]) ;
40336                         return end+2;
40337                 }else{//error
40338                         return -1;
40339                 }
40340         }
40341         return -1;
40342 }
40343
40344 /**
40345  * @param source
40346  */
40347 function ElementAttributes(source){
40348         
40349 }
40350 ElementAttributes.prototype = {
40351         setTagName:function(tagName){
40352                 if(!tagNamePattern.test(tagName)){
40353                         throw new Error('invalid tagName:'+tagName)
40354                 }
40355                 this.tagName = tagName;
40356         },
40357         add:function(qName,value,offset){
40358                 if(!tagNamePattern.test(qName)){
40359                         throw new Error('invalid attribute:'+qName)
40360                 }
40361                 this[this.length++] = {qName:qName,value:value,offset:offset};
40362         },
40363         length:0,
40364         getLocalName:function(i){return this[i].localName},
40365         getOffset:function(i){return this[i].offset},
40366         getQName:function(i){return this[i].qName},
40367         getURI:function(i){return this[i].uri},
40368         getValue:function(i){return this[i].value}
40369 //      ,getIndex:function(uri, localName)){
40370 //              if(localName){
40371 //                      
40372 //              }else{
40373 //                      var qName = uri
40374 //              }
40375 //      },
40376 //      getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
40377 //      getType:function(uri,localName){}
40378 //      getType:function(i){},
40379 };
40380
40381
40382
40383
40384 function _set_proto_(thiz,parent){
40385         thiz.__proto__ = parent;
40386         return thiz;
40387 }
40388 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
40389         _set_proto_ = function(thiz,parent){
40390                 function p(){}
40391                 p.prototype = parent;
40392                 p = new p();
40393                 for(parent in thiz){
40394                         p[parent] = thiz[parent];
40395                 }
40396                 return p;
40397         };
40398 }
40399
40400 function split(source,start){
40401         var match;
40402         var buf = [];
40403         var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
40404         reg.lastIndex = start;
40405         reg.exec(source);//skip <
40406         while(match = reg.exec(source)){
40407                 buf.push(match);
40408                 if(match[1])return buf;
40409         }
40410 }
40411
40412 if(typeof commonjsRequire == 'function'){
40413         exports.XMLReader = XMLReader;
40414 }
40415 });
40416
40417 var dom = createCommonjsModule(function (module, exports) {
40418 /*
40419  * DOM Level 2
40420  * Object DOMException
40421  * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
40422  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
40423  */
40424
40425 function copy(src,dest){
40426         for(var p in src){
40427                 dest[p] = src[p];
40428         }
40429 }
40430 /**
40431 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
40432 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
40433  */
40434 function _extends(Class,Super){
40435         var pt = Class.prototype;
40436         if(Object.create){
40437                 var ppt = Object.create(Super.prototype);
40438                 pt.__proto__ = ppt;
40439         }
40440         if(!(pt instanceof Super)){
40441                 function t(){}
40442                 t.prototype = Super.prototype;
40443                 t = new t();
40444                 copy(pt,t);
40445                 Class.prototype = pt = t;
40446         }
40447         if(pt.constructor != Class){
40448                 if(typeof Class != 'function'){
40449                         console.error("unknow Class:"+Class);
40450                 }
40451                 pt.constructor = Class;
40452         }
40453 }
40454 var htmlns = 'http://www.w3.org/1999/xhtml';
40455 // Node Types
40456 var NodeType = {};
40457 var ELEMENT_NODE                = NodeType.ELEMENT_NODE                = 1;
40458 var ATTRIBUTE_NODE              = NodeType.ATTRIBUTE_NODE              = 2;
40459 var TEXT_NODE                   = NodeType.TEXT_NODE                   = 3;
40460 var CDATA_SECTION_NODE          = NodeType.CDATA_SECTION_NODE          = 4;
40461 var ENTITY_REFERENCE_NODE       = NodeType.ENTITY_REFERENCE_NODE       = 5;
40462 var ENTITY_NODE                 = NodeType.ENTITY_NODE                 = 6;
40463 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
40464 var COMMENT_NODE                = NodeType.COMMENT_NODE                = 8;
40465 var DOCUMENT_NODE               = NodeType.DOCUMENT_NODE               = 9;
40466 var DOCUMENT_TYPE_NODE          = NodeType.DOCUMENT_TYPE_NODE          = 10;
40467 var DOCUMENT_FRAGMENT_NODE      = NodeType.DOCUMENT_FRAGMENT_NODE      = 11;
40468 var NOTATION_NODE               = NodeType.NOTATION_NODE               = 12;
40469
40470 // ExceptionCode
40471 var ExceptionCode = {};
40472 var ExceptionMessage = {};
40473 var INDEX_SIZE_ERR              = ExceptionCode.INDEX_SIZE_ERR              = ((ExceptionMessage[1]="Index size error"),1);
40474 var DOMSTRING_SIZE_ERR          = ExceptionCode.DOMSTRING_SIZE_ERR          = ((ExceptionMessage[2]="DOMString size error"),2);
40475 var HIERARCHY_REQUEST_ERR       = ExceptionCode.HIERARCHY_REQUEST_ERR       = ((ExceptionMessage[3]="Hierarchy request error"),3);
40476 var WRONG_DOCUMENT_ERR          = ExceptionCode.WRONG_DOCUMENT_ERR          = ((ExceptionMessage[4]="Wrong document"),4);
40477 var INVALID_CHARACTER_ERR       = ExceptionCode.INVALID_CHARACTER_ERR       = ((ExceptionMessage[5]="Invalid character"),5);
40478 var NO_DATA_ALLOWED_ERR         = ExceptionCode.NO_DATA_ALLOWED_ERR         = ((ExceptionMessage[6]="No data allowed"),6);
40479 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
40480 var NOT_FOUND_ERR               = ExceptionCode.NOT_FOUND_ERR               = ((ExceptionMessage[8]="Not found"),8);
40481 var NOT_SUPPORTED_ERR           = ExceptionCode.NOT_SUPPORTED_ERR           = ((ExceptionMessage[9]="Not supported"),9);
40482 var INUSE_ATTRIBUTE_ERR         = ExceptionCode.INUSE_ATTRIBUTE_ERR         = ((ExceptionMessage[10]="Attribute in use"),10);
40483 //level2
40484 var INVALID_STATE_ERR           = ExceptionCode.INVALID_STATE_ERR               = ((ExceptionMessage[11]="Invalid state"),11);
40485 var SYNTAX_ERR                  = ExceptionCode.SYNTAX_ERR                      = ((ExceptionMessage[12]="Syntax error"),12);
40486 var INVALID_MODIFICATION_ERR    = ExceptionCode.INVALID_MODIFICATION_ERR        = ((ExceptionMessage[13]="Invalid modification"),13);
40487 var NAMESPACE_ERR               = ExceptionCode.NAMESPACE_ERR                   = ((ExceptionMessage[14]="Invalid namespace"),14);
40488 var INVALID_ACCESS_ERR          = ExceptionCode.INVALID_ACCESS_ERR              = ((ExceptionMessage[15]="Invalid access"),15);
40489
40490
40491 function DOMException(code, message) {
40492         if(message instanceof Error){
40493                 var error = message;
40494         }else{
40495                 error = this;
40496                 Error.call(this, ExceptionMessage[code]);
40497                 this.message = ExceptionMessage[code];
40498                 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
40499         }
40500         error.code = code;
40501         if(message) this.message = this.message + ": " + message;
40502         return error;
40503 }
40504 DOMException.prototype = Error.prototype;
40505 copy(ExceptionCode,DOMException);
40506 /**
40507  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
40508  * 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.
40509  * The items in the NodeList are accessible via an integral index, starting from 0.
40510  */
40511 function NodeList() {
40512 }
40513 NodeList.prototype = {
40514         /**
40515          * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
40516          * @standard level1
40517          */
40518         length:0, 
40519         /**
40520          * 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.
40521          * @standard level1
40522          * @param index  unsigned long 
40523          *   Index into the collection.
40524          * @return Node
40525          *      The node at the indexth position in the NodeList, or null if that is not a valid index. 
40526          */
40527         item: function(index) {
40528                 return this[index] || null;
40529         },
40530         toString:function(){
40531                 for(var buf = [], i = 0;i<this.length;i++){
40532                         serializeToString(this[i],buf);
40533                 }
40534                 return buf.join('');
40535         }
40536 };
40537 function LiveNodeList(node,refresh){
40538         this._node = node;
40539         this._refresh = refresh;
40540         _updateLiveList(this);
40541 }
40542 function _updateLiveList(list){
40543         var inc = list._node._inc || list._node.ownerDocument._inc;
40544         if(list._inc != inc){
40545                 var ls = list._refresh(list._node);
40546                 //console.log(ls.length)
40547                 __set__(list,'length',ls.length);
40548                 copy(ls,list);
40549                 list._inc = inc;
40550         }
40551 }
40552 LiveNodeList.prototype.item = function(i){
40553         _updateLiveList(this);
40554         return this[i];
40555 };
40556
40557 _extends(LiveNodeList,NodeList);
40558 /**
40559  * 
40560  * 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.
40561  * NamedNodeMap objects in the DOM are live.
40562  * used for attributes or DocumentType entities 
40563  */
40564 function NamedNodeMap() {
40565 }
40566
40567 function _findNodeIndex(list,node){
40568         var i = list.length;
40569         while(i--){
40570                 if(list[i] === node){return i}
40571         }
40572 }
40573
40574 function _addNamedNode(el,list,newAttr,oldAttr){
40575         if(oldAttr){
40576                 list[_findNodeIndex(list,oldAttr)] = newAttr;
40577         }else{
40578                 list[list.length++] = newAttr;
40579         }
40580         if(el){
40581                 newAttr.ownerElement = el;
40582                 var doc = el.ownerDocument;
40583                 if(doc){
40584                         oldAttr && _onRemoveAttribute(doc,el,oldAttr);
40585                         _onAddAttribute(doc,el,newAttr);
40586                 }
40587         }
40588 }
40589 function _removeNamedNode(el,list,attr){
40590         var i = _findNodeIndex(list,attr);
40591         if(i>=0){
40592                 var lastIndex = list.length-1;
40593                 while(i<lastIndex){
40594                         list[i] = list[++i];
40595                 }
40596                 list.length = lastIndex;
40597                 if(el){
40598                         var doc = el.ownerDocument;
40599                         if(doc){
40600                                 _onRemoveAttribute(doc,el,attr);
40601                                 attr.ownerElement = null;
40602                         }
40603                 }
40604         }else{
40605                 throw DOMException(NOT_FOUND_ERR,new Error())
40606         }
40607 }
40608 NamedNodeMap.prototype = {
40609         length:0,
40610         item:NodeList.prototype.item,
40611         getNamedItem: function(key) {
40612 //              if(key.indexOf(':')>0 || key == 'xmlns'){
40613 //                      return null;
40614 //              }
40615                 var i = this.length;
40616                 while(i--){
40617                         var attr = this[i];
40618                         if(attr.nodeName == key){
40619                                 return attr;
40620                         }
40621                 }
40622         },
40623         setNamedItem: function(attr) {
40624                 var el = attr.ownerElement;
40625                 if(el && el!=this._ownerElement){
40626                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
40627                 }
40628                 var oldAttr = this.getNamedItem(attr.nodeName);
40629                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
40630                 return oldAttr;
40631         },
40632         /* returns Node */
40633         setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
40634                 var el = attr.ownerElement, oldAttr;
40635                 if(el && el!=this._ownerElement){
40636                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
40637                 }
40638                 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
40639                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
40640                 return oldAttr;
40641         },
40642
40643         /* returns Node */
40644         removeNamedItem: function(key) {
40645                 var attr = this.getNamedItem(key);
40646                 _removeNamedNode(this._ownerElement,this,attr);
40647                 return attr;
40648                 
40649                 
40650         },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
40651         
40652         //for level2
40653         removeNamedItemNS:function(namespaceURI,localName){
40654                 var attr = this.getNamedItemNS(namespaceURI,localName);
40655                 _removeNamedNode(this._ownerElement,this,attr);
40656                 return attr;
40657         },
40658         getNamedItemNS: function(namespaceURI, localName) {
40659                 var i = this.length;
40660                 while(i--){
40661                         var node = this[i];
40662                         if(node.localName == localName && node.namespaceURI == namespaceURI){
40663                                 return node;
40664                         }
40665                 }
40666                 return null;
40667         }
40668 };
40669 /**
40670  * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
40671  */
40672 function DOMImplementation(/* Object */ features) {
40673         this._features = {};
40674         if (features) {
40675                 for (var feature in features) {
40676                          this._features = features[feature];
40677                 }
40678         }
40679 }
40680
40681 DOMImplementation.prototype = {
40682         hasFeature: function(/* string */ feature, /* string */ version) {
40683                 var versions = this._features[feature.toLowerCase()];
40684                 if (versions && (!version || version in versions)) {
40685                         return true;
40686                 } else {
40687                         return false;
40688                 }
40689         },
40690         // Introduced in DOM Level 2:
40691         createDocument:function(namespaceURI,  qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
40692                 var doc = new Document();
40693                 doc.implementation = this;
40694                 doc.childNodes = new NodeList();
40695                 doc.doctype = doctype;
40696                 if(doctype){
40697                         doc.appendChild(doctype);
40698                 }
40699                 if(qualifiedName){
40700                         var root = doc.createElementNS(namespaceURI,qualifiedName);
40701                         doc.appendChild(root);
40702                 }
40703                 return doc;
40704         },
40705         // Introduced in DOM Level 2:
40706         createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
40707                 var node = new DocumentType();
40708                 node.name = qualifiedName;
40709                 node.nodeName = qualifiedName;
40710                 node.publicId = publicId;
40711                 node.systemId = systemId;
40712                 // Introduced in DOM Level 2:
40713                 //readonly attribute DOMString        internalSubset;
40714                 
40715                 //TODO:..
40716                 //  readonly attribute NamedNodeMap     entities;
40717                 //  readonly attribute NamedNodeMap     notations;
40718                 return node;
40719         }
40720 };
40721
40722
40723 /**
40724  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
40725  */
40726
40727 function Node() {
40728 }
40729
40730 Node.prototype = {
40731         firstChild : null,
40732         lastChild : null,
40733         previousSibling : null,
40734         nextSibling : null,
40735         attributes : null,
40736         parentNode : null,
40737         childNodes : null,
40738         ownerDocument : null,
40739         nodeValue : null,
40740         namespaceURI : null,
40741         prefix : null,
40742         localName : null,
40743         // Modified in DOM Level 2:
40744         insertBefore:function(newChild, refChild){//raises 
40745                 return _insertBefore(this,newChild,refChild);
40746         },
40747         replaceChild:function(newChild, oldChild){//raises 
40748                 this.insertBefore(newChild,oldChild);
40749                 if(oldChild){
40750                         this.removeChild(oldChild);
40751                 }
40752         },
40753         removeChild:function(oldChild){
40754                 return _removeChild(this,oldChild);
40755         },
40756         appendChild:function(newChild){
40757                 return this.insertBefore(newChild,null);
40758         },
40759         hasChildNodes:function(){
40760                 return this.firstChild != null;
40761         },
40762         cloneNode:function(deep){
40763                 return cloneNode(this.ownerDocument||this,this,deep);
40764         },
40765         // Modified in DOM Level 2:
40766         normalize:function(){
40767                 var child = this.firstChild;
40768                 while(child){
40769                         var next = child.nextSibling;
40770                         if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
40771                                 this.removeChild(next);
40772                                 child.appendData(next.data);
40773                         }else{
40774                                 child.normalize();
40775                                 child = next;
40776                         }
40777                 }
40778         },
40779         // Introduced in DOM Level 2:
40780         isSupported:function(feature, version){
40781                 return this.ownerDocument.implementation.hasFeature(feature,version);
40782         },
40783     // Introduced in DOM Level 2:
40784     hasAttributes:function(){
40785         return this.attributes.length>0;
40786     },
40787     lookupPrefix:function(namespaceURI){
40788         var el = this;
40789         while(el){
40790                 var map = el._nsMap;
40791                 //console.dir(map)
40792                 if(map){
40793                         for(var n in map){
40794                                 if(map[n] == namespaceURI){
40795                                         return n;
40796                                 }
40797                         }
40798                 }
40799                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
40800         }
40801         return null;
40802     },
40803     // Introduced in DOM Level 3:
40804     lookupNamespaceURI:function(prefix){
40805         var el = this;
40806         while(el){
40807                 var map = el._nsMap;
40808                 //console.dir(map)
40809                 if(map){
40810                         if(prefix in map){
40811                                 return map[prefix] ;
40812                         }
40813                 }
40814                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
40815         }
40816         return null;
40817     },
40818     // Introduced in DOM Level 3:
40819     isDefaultNamespace:function(namespaceURI){
40820         var prefix = this.lookupPrefix(namespaceURI);
40821         return prefix == null;
40822     }
40823 };
40824
40825
40826 function _xmlEncoder(c){
40827         return c == '<' && '&lt;' ||
40828          c == '>' && '&gt;' ||
40829          c == '&' && '&amp;' ||
40830          c == '"' && '&quot;' ||
40831          '&#'+c.charCodeAt()+';'
40832 }
40833
40834
40835 copy(NodeType,Node);
40836 copy(NodeType,Node.prototype);
40837
40838 /**
40839  * @param callback return true for continue,false for break
40840  * @return boolean true: break visit;
40841  */
40842 function _visitNode(node,callback){
40843         if(callback(node)){
40844                 return true;
40845         }
40846         if(node = node.firstChild){
40847                 do{
40848                         if(_visitNode(node,callback)){return true}
40849         }while(node=node.nextSibling)
40850     }
40851 }
40852
40853
40854
40855 function Document(){
40856 }
40857 function _onAddAttribute(doc,el,newAttr){
40858         doc && doc._inc++;
40859         var ns = newAttr.namespaceURI;
40860         if(ns == 'http://www.w3.org/2000/xmlns/'){
40861                 //update namespace
40862                 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
40863         }
40864 }
40865 function _onRemoveAttribute(doc,el,newAttr,remove){
40866         doc && doc._inc++;
40867         var ns = newAttr.namespaceURI;
40868         if(ns == 'http://www.w3.org/2000/xmlns/'){
40869                 //update namespace
40870                 delete el._nsMap[newAttr.prefix?newAttr.localName:''];
40871         }
40872 }
40873 function _onUpdateChild(doc,el,newChild){
40874         if(doc && doc._inc){
40875                 doc._inc++;
40876                 //update childNodes
40877                 var cs = el.childNodes;
40878                 if(newChild){
40879                         cs[cs.length++] = newChild;
40880                 }else{
40881                         //console.log(1)
40882                         var child = el.firstChild;
40883                         var i = 0;
40884                         while(child){
40885                                 cs[i++] = child;
40886                                 child =child.nextSibling;
40887                         }
40888                         cs.length = i;
40889                 }
40890         }
40891 }
40892
40893 /**
40894  * attributes;
40895  * children;
40896  * 
40897  * writeable properties:
40898  * nodeValue,Attr:value,CharacterData:data
40899  * prefix
40900  */
40901 function _removeChild(parentNode,child){
40902         var previous = child.previousSibling;
40903         var next = child.nextSibling;
40904         if(previous){
40905                 previous.nextSibling = next;
40906         }else{
40907                 parentNode.firstChild = next;
40908         }
40909         if(next){
40910                 next.previousSibling = previous;
40911         }else{
40912                 parentNode.lastChild = previous;
40913         }
40914         _onUpdateChild(parentNode.ownerDocument,parentNode);
40915         return child;
40916 }
40917 /**
40918  * preformance key(refChild == null)
40919  */
40920 function _insertBefore(parentNode,newChild,nextChild){
40921         var cp = newChild.parentNode;
40922         if(cp){
40923                 cp.removeChild(newChild);//remove and update
40924         }
40925         if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
40926                 var newFirst = newChild.firstChild;
40927                 if (newFirst == null) {
40928                         return newChild;
40929                 }
40930                 var newLast = newChild.lastChild;
40931         }else{
40932                 newFirst = newLast = newChild;
40933         }
40934         var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
40935
40936         newFirst.previousSibling = pre;
40937         newLast.nextSibling = nextChild;
40938         
40939         
40940         if(pre){
40941                 pre.nextSibling = newFirst;
40942         }else{
40943                 parentNode.firstChild = newFirst;
40944         }
40945         if(nextChild == null){
40946                 parentNode.lastChild = newLast;
40947         }else{
40948                 nextChild.previousSibling = newLast;
40949         }
40950         do{
40951                 newFirst.parentNode = parentNode;
40952         }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
40953         _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
40954         //console.log(parentNode.lastChild.nextSibling == null)
40955         if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
40956                 newChild.firstChild = newChild.lastChild = null;
40957         }
40958         return newChild;
40959 }
40960 function _appendSingleChild(parentNode,newChild){
40961         var cp = newChild.parentNode;
40962         if(cp){
40963                 var pre = parentNode.lastChild;
40964                 cp.removeChild(newChild);//remove and update
40965                 var pre = parentNode.lastChild;
40966         }
40967         var pre = parentNode.lastChild;
40968         newChild.parentNode = parentNode;
40969         newChild.previousSibling = pre;
40970         newChild.nextSibling = null;
40971         if(pre){
40972                 pre.nextSibling = newChild;
40973         }else{
40974                 parentNode.firstChild = newChild;
40975         }
40976         parentNode.lastChild = newChild;
40977         _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
40978         return newChild;
40979         //console.log("__aa",parentNode.lastChild.nextSibling == null)
40980 }
40981 Document.prototype = {
40982         //implementation : null,
40983         nodeName :  '#document',
40984         nodeType :  DOCUMENT_NODE,
40985         doctype :  null,
40986         documentElement :  null,
40987         _inc : 1,
40988         
40989         insertBefore :  function(newChild, refChild){//raises 
40990                 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
40991                         var child = newChild.firstChild;
40992                         while(child){
40993                                 var next = child.nextSibling;
40994                                 this.insertBefore(child,refChild);
40995                                 child = next;
40996                         }
40997                         return newChild;
40998                 }
40999                 if(this.documentElement == null && newChild.nodeType == 1){
41000                         this.documentElement = newChild;
41001                 }
41002                 
41003                 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
41004         },
41005         removeChild :  function(oldChild){
41006                 if(this.documentElement == oldChild){
41007                         this.documentElement = null;
41008                 }
41009                 return _removeChild(this,oldChild);
41010         },
41011         // Introduced in DOM Level 2:
41012         importNode : function(importedNode,deep){
41013                 return importNode(this,importedNode,deep);
41014         },
41015         // Introduced in DOM Level 2:
41016         getElementById :        function(id){
41017                 var rtv = null;
41018                 _visitNode(this.documentElement,function(node){
41019                         if(node.nodeType == 1){
41020                                 if(node.getAttribute('id') == id){
41021                                         rtv = node;
41022                                         return true;
41023                                 }
41024                         }
41025                 });
41026                 return rtv;
41027         },
41028         
41029         //document factory method:
41030         createElement : function(tagName){
41031                 var node = new Element();
41032                 node.ownerDocument = this;
41033                 node.nodeName = tagName;
41034                 node.tagName = tagName;
41035                 node.childNodes = new NodeList();
41036                 var attrs       = node.attributes = new NamedNodeMap();
41037                 attrs._ownerElement = node;
41038                 return node;
41039         },
41040         createDocumentFragment :        function(){
41041                 var node = new DocumentFragment();
41042                 node.ownerDocument = this;
41043                 node.childNodes = new NodeList();
41044                 return node;
41045         },
41046         createTextNode :        function(data){
41047                 var node = new Text();
41048                 node.ownerDocument = this;
41049                 node.appendData(data);
41050                 return node;
41051         },
41052         createComment : function(data){
41053                 var node = new Comment();
41054                 node.ownerDocument = this;
41055                 node.appendData(data);
41056                 return node;
41057         },
41058         createCDATASection :    function(data){
41059                 var node = new CDATASection();
41060                 node.ownerDocument = this;
41061                 node.appendData(data);
41062                 return node;
41063         },
41064         createProcessingInstruction :   function(target,data){
41065                 var node = new ProcessingInstruction();
41066                 node.ownerDocument = this;
41067                 node.tagName = node.target = target;
41068                 node.nodeValue= node.data = data;
41069                 return node;
41070         },
41071         createAttribute :       function(name){
41072                 var node = new Attr();
41073                 node.ownerDocument      = this;
41074                 node.name = name;
41075                 node.nodeName   = name;
41076                 node.localName = name;
41077                 node.specified = true;
41078                 return node;
41079         },
41080         createEntityReference : function(name){
41081                 var node = new EntityReference();
41082                 node.ownerDocument      = this;
41083                 node.nodeName   = name;
41084                 return node;
41085         },
41086         // Introduced in DOM Level 2:
41087         createElementNS :       function(namespaceURI,qualifiedName){
41088                 var node = new Element();
41089                 var pl = qualifiedName.split(':');
41090                 var attrs       = node.attributes = new NamedNodeMap();
41091                 node.childNodes = new NodeList();
41092                 node.ownerDocument = this;
41093                 node.nodeName = qualifiedName;
41094                 node.tagName = qualifiedName;
41095                 node.namespaceURI = namespaceURI;
41096                 if(pl.length == 2){
41097                         node.prefix = pl[0];
41098                         node.localName = pl[1];
41099                 }else{
41100                         //el.prefix = null;
41101                         node.localName = qualifiedName;
41102                 }
41103                 attrs._ownerElement = node;
41104                 return node;
41105         },
41106         // Introduced in DOM Level 2:
41107         createAttributeNS :     function(namespaceURI,qualifiedName){
41108                 var node = new Attr();
41109                 var pl = qualifiedName.split(':');
41110                 node.ownerDocument = this;
41111                 node.nodeName = qualifiedName;
41112                 node.name = qualifiedName;
41113                 node.namespaceURI = namespaceURI;
41114                 node.specified = true;
41115                 if(pl.length == 2){
41116                         node.prefix = pl[0];
41117                         node.localName = pl[1];
41118                 }else{
41119                         //el.prefix = null;
41120                         node.localName = qualifiedName;
41121                 }
41122                 return node;
41123         }
41124 };
41125 _extends(Document,Node);
41126
41127
41128 function Element() {
41129         this._nsMap = {};
41130 }
41131 Element.prototype = {
41132         nodeType : ELEMENT_NODE,
41133         hasAttribute : function(name){
41134                 return this.getAttributeNode(name)!=null;
41135         },
41136         getAttribute : function(name){
41137                 var attr = this.getAttributeNode(name);
41138                 return attr && attr.value || '';
41139         },
41140         getAttributeNode : function(name){
41141                 return this.attributes.getNamedItem(name);
41142         },
41143         setAttribute : function(name, value){
41144                 var attr = this.ownerDocument.createAttribute(name);
41145                 attr.value = attr.nodeValue = "" + value;
41146                 this.setAttributeNode(attr);
41147         },
41148         removeAttribute : function(name){
41149                 var attr = this.getAttributeNode(name);
41150                 attr && this.removeAttributeNode(attr);
41151         },
41152         
41153         //four real opeartion method
41154         appendChild:function(newChild){
41155                 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41156                         return this.insertBefore(newChild,null);
41157                 }else{
41158                         return _appendSingleChild(this,newChild);
41159                 }
41160         },
41161         setAttributeNode : function(newAttr){
41162                 return this.attributes.setNamedItem(newAttr);
41163         },
41164         setAttributeNodeNS : function(newAttr){
41165                 return this.attributes.setNamedItemNS(newAttr);
41166         },
41167         removeAttributeNode : function(oldAttr){
41168                 return this.attributes.removeNamedItem(oldAttr.nodeName);
41169         },
41170         //get real attribute name,and remove it by removeAttributeNode
41171         removeAttributeNS : function(namespaceURI, localName){
41172                 var old = this.getAttributeNodeNS(namespaceURI, localName);
41173                 old && this.removeAttributeNode(old);
41174         },
41175         
41176         hasAttributeNS : function(namespaceURI, localName){
41177                 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
41178         },
41179         getAttributeNS : function(namespaceURI, localName){
41180                 var attr = this.getAttributeNodeNS(namespaceURI, localName);
41181                 return attr && attr.value || '';
41182         },
41183         setAttributeNS : function(namespaceURI, qualifiedName, value){
41184                 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
41185                 attr.value = attr.nodeValue = "" + value;
41186                 this.setAttributeNode(attr);
41187         },
41188         getAttributeNodeNS : function(namespaceURI, localName){
41189                 return this.attributes.getNamedItemNS(namespaceURI, localName);
41190         },
41191         
41192         getElementsByTagName : function(tagName){
41193                 return new LiveNodeList(this,function(base){
41194                         var ls = [];
41195                         _visitNode(base,function(node){
41196                                 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
41197                                         ls.push(node);
41198                                 }
41199                         });
41200                         return ls;
41201                 });
41202         },
41203         getElementsByTagNameNS : function(namespaceURI, localName){
41204                 return new LiveNodeList(this,function(base){
41205                         var ls = [];
41206                         _visitNode(base,function(node){
41207                                 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
41208                                         ls.push(node);
41209                                 }
41210                         });
41211                         return ls;
41212                 });
41213         }
41214 };
41215 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
41216 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
41217
41218
41219 _extends(Element,Node);
41220 function Attr() {
41221 }
41222 Attr.prototype.nodeType = ATTRIBUTE_NODE;
41223 _extends(Attr,Node);
41224
41225
41226 function CharacterData() {
41227 }
41228 CharacterData.prototype = {
41229         data : '',
41230         substringData : function(offset, count) {
41231                 return this.data.substring(offset, offset+count);
41232         },
41233         appendData: function(text) {
41234                 text = this.data+text;
41235                 this.nodeValue = this.data = text;
41236                 this.length = text.length;
41237         },
41238         insertData: function(offset,text) {
41239                 this.replaceData(offset,0,text);
41240         
41241         },
41242         appendChild:function(newChild){
41243                 //if(!(newChild instanceof CharacterData)){
41244                         throw new Error(ExceptionMessage[3])
41245                 //}
41246                 return Node.prototype.appendChild.apply(this,arguments)
41247         },
41248         deleteData: function(offset, count) {
41249                 this.replaceData(offset,count,"");
41250         },
41251         replaceData: function(offset, count, text) {
41252                 var start = this.data.substring(0,offset);
41253                 var end = this.data.substring(offset+count);
41254                 text = start + text + end;
41255                 this.nodeValue = this.data = text;
41256                 this.length = text.length;
41257         }
41258 };
41259 _extends(CharacterData,Node);
41260 function Text() {
41261 }
41262 Text.prototype = {
41263         nodeName : "#text",
41264         nodeType : TEXT_NODE,
41265         splitText : function(offset) {
41266                 var text = this.data;
41267                 var newText = text.substring(offset);
41268                 text = text.substring(0, offset);
41269                 this.data = this.nodeValue = text;
41270                 this.length = text.length;
41271                 var newNode = this.ownerDocument.createTextNode(newText);
41272                 if(this.parentNode){
41273                         this.parentNode.insertBefore(newNode, this.nextSibling);
41274                 }
41275                 return newNode;
41276         }
41277 };
41278 _extends(Text,CharacterData);
41279 function Comment() {
41280 }
41281 Comment.prototype = {
41282         nodeName : "#comment",
41283         nodeType : COMMENT_NODE
41284 };
41285 _extends(Comment,CharacterData);
41286
41287 function CDATASection() {
41288 }
41289 CDATASection.prototype = {
41290         nodeName : "#cdata-section",
41291         nodeType : CDATA_SECTION_NODE
41292 };
41293 _extends(CDATASection,CharacterData);
41294
41295
41296 function DocumentType() {
41297 }
41298 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
41299 _extends(DocumentType,Node);
41300
41301 function Notation() {
41302 }
41303 Notation.prototype.nodeType = NOTATION_NODE;
41304 _extends(Notation,Node);
41305
41306 function Entity() {
41307 }
41308 Entity.prototype.nodeType = ENTITY_NODE;
41309 _extends(Entity,Node);
41310
41311 function EntityReference() {
41312 }
41313 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
41314 _extends(EntityReference,Node);
41315
41316 function DocumentFragment() {
41317 }
41318 DocumentFragment.prototype.nodeName =   "#document-fragment";
41319 DocumentFragment.prototype.nodeType =   DOCUMENT_FRAGMENT_NODE;
41320 _extends(DocumentFragment,Node);
41321
41322
41323 function ProcessingInstruction() {
41324 }
41325 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
41326 _extends(ProcessingInstruction,Node);
41327 function XMLSerializer(){}
41328 XMLSerializer.prototype.serializeToString = function(node,attributeSorter){
41329         return node.toString(attributeSorter);
41330 };
41331 Node.prototype.toString =function(attributeSorter){
41332         var buf = [];
41333         serializeToString(this,buf,attributeSorter);
41334         return buf.join('');
41335 };
41336 function serializeToString(node,buf,attributeSorter,isHTML){
41337         switch(node.nodeType){
41338         case ELEMENT_NODE:
41339                 var attrs = node.attributes;
41340                 var len = attrs.length;
41341                 var child = node.firstChild;
41342                 var nodeName = node.tagName;
41343                 isHTML =  (htmlns === node.namespaceURI) ||isHTML; 
41344                 buf.push('<',nodeName);
41345                 if(attributeSorter){
41346                         buf.sort.apply(attrs, attributeSorter);
41347                 }
41348                 for(var i=0;i<len;i++){
41349                         serializeToString(attrs.item(i),buf,attributeSorter,isHTML);
41350                 }
41351                 if(child || isHTML && !/^(?:meta|link|img|br|hr|input|button)$/i.test(nodeName)){
41352                         buf.push('>');
41353                         //if is cdata child node
41354                         if(isHTML && /^script$/i.test(nodeName)){
41355                                 if(child){
41356                                         buf.push(child.data);
41357                                 }
41358                         }else{
41359                                 while(child){
41360                                         serializeToString(child,buf,attributeSorter,isHTML);
41361                                         child = child.nextSibling;
41362                                 }
41363                         }
41364                         buf.push('</',nodeName,'>');
41365                 }else{
41366                         buf.push('/>');
41367                 }
41368                 return;
41369         case DOCUMENT_NODE:
41370         case DOCUMENT_FRAGMENT_NODE:
41371                 var child = node.firstChild;
41372                 while(child){
41373                         serializeToString(child,buf,attributeSorter,isHTML);
41374                         child = child.nextSibling;
41375                 }
41376                 return;
41377         case ATTRIBUTE_NODE:
41378                 return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
41379         case TEXT_NODE:
41380                 return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
41381         case CDATA_SECTION_NODE:
41382                 return buf.push( '<![CDATA[',node.data,']]>');
41383         case COMMENT_NODE:
41384                 return buf.push( "<!--",node.data,"-->");
41385         case DOCUMENT_TYPE_NODE:
41386                 var pubid = node.publicId;
41387                 var sysid = node.systemId;
41388                 buf.push('<!DOCTYPE ',node.name);
41389                 if(pubid){
41390                         buf.push(' PUBLIC "',pubid);
41391                         if (sysid && sysid!='.') {
41392                                 buf.push( '" "',sysid);
41393                         }
41394                         buf.push('">');
41395                 }else if(sysid && sysid!='.'){
41396                         buf.push(' SYSTEM "',sysid,'">');
41397                 }else{
41398                         var sub = node.internalSubset;
41399                         if(sub){
41400                                 buf.push(" [",sub,"]");
41401                         }
41402                         buf.push(">");
41403                 }
41404                 return;
41405         case PROCESSING_INSTRUCTION_NODE:
41406                 return buf.push( "<?",node.target," ",node.data,"?>");
41407         case ENTITY_REFERENCE_NODE:
41408                 return buf.push( '&',node.nodeName,';');
41409         //case ENTITY_NODE:
41410         //case NOTATION_NODE:
41411         default:
41412                 buf.push('??',node.nodeName);
41413         }
41414 }
41415 function importNode(doc,node,deep){
41416         var node2;
41417         switch (node.nodeType) {
41418         case ELEMENT_NODE:
41419                 node2 = node.cloneNode(false);
41420                 node2.ownerDocument = doc;
41421                 //var attrs = node2.attributes;
41422                 //var len = attrs.length;
41423                 //for(var i=0;i<len;i++){
41424                         //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
41425                 //}
41426         case DOCUMENT_FRAGMENT_NODE:
41427                 break;
41428         case ATTRIBUTE_NODE:
41429                 deep = true;
41430                 break;
41431         //case ENTITY_REFERENCE_NODE:
41432         //case PROCESSING_INSTRUCTION_NODE:
41433         ////case TEXT_NODE:
41434         //case CDATA_SECTION_NODE:
41435         //case COMMENT_NODE:
41436         //      deep = false;
41437         //      break;
41438         //case DOCUMENT_NODE:
41439         //case DOCUMENT_TYPE_NODE:
41440         //cannot be imported.
41441         //case ENTITY_NODE:
41442         //case NOTATION_NODE:
41443         //can not hit in level3
41444         //default:throw e;
41445         }
41446         if(!node2){
41447                 node2 = node.cloneNode(false);//false
41448         }
41449         node2.ownerDocument = doc;
41450         node2.parentNode = null;
41451         if(deep){
41452                 var child = node.firstChild;
41453                 while(child){
41454                         node2.appendChild(importNode(doc,child,deep));
41455                         child = child.nextSibling;
41456                 }
41457         }
41458         return node2;
41459 }
41460 //
41461 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
41462 //                                      attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
41463 function cloneNode(doc,node,deep){
41464         var node2 = new node.constructor();
41465         for(var n in node){
41466                 var v = node[n];
41467                 if(typeof v != 'object' ){
41468                         if(v != node2[n]){
41469                                 node2[n] = v;
41470                         }
41471                 }
41472         }
41473         if(node.childNodes){
41474                 node2.childNodes = new NodeList();
41475         }
41476         node2.ownerDocument = doc;
41477         switch (node2.nodeType) {
41478         case ELEMENT_NODE:
41479                 var attrs       = node.attributes;
41480                 var attrs2      = node2.attributes = new NamedNodeMap();
41481                 var len = attrs.length;
41482                 attrs2._ownerElement = node2;
41483                 for(var i=0;i<len;i++){
41484                         node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
41485                 }
41486                 break;;
41487         case ATTRIBUTE_NODE:
41488                 deep = true;
41489         }
41490         if(deep){
41491                 var child = node.firstChild;
41492                 while(child){
41493                         node2.appendChild(cloneNode(doc,child,deep));
41494                         child = child.nextSibling;
41495                 }
41496         }
41497         return node2;
41498 }
41499
41500 function __set__(object,key,value){
41501         object[key] = value;
41502 }
41503 //do dynamic
41504 try{
41505         if(Object.defineProperty){
41506                 Object.defineProperty(LiveNodeList.prototype,'length',{
41507                         get:function(){
41508                                 _updateLiveList(this);
41509                                 return this.$$length;
41510                         }
41511                 });
41512                 Object.defineProperty(Node.prototype,'textContent',{
41513                         get:function(){
41514                                 return getTextContent(this);
41515                         },
41516                         set:function(data){
41517                                 switch(this.nodeType){
41518                                 case 1:
41519                                 case 11:
41520                                         while(this.firstChild){
41521                                                 this.removeChild(this.firstChild);
41522                                         }
41523                                         if(data || String(data)){
41524                                                 this.appendChild(this.ownerDocument.createTextNode(data));
41525                                         }
41526                                         break;
41527                                 default:
41528                                         //TODO:
41529                                         this.data = data;
41530                                         this.value = value;
41531                                         this.nodeValue = data;
41532                                 }
41533                         }
41534                 });
41535                 
41536                 function getTextContent(node){
41537                         switch(node.nodeType){
41538                         case 1:
41539                         case 11:
41540                                 var buf = [];
41541                                 node = node.firstChild;
41542                                 while(node){
41543                                         if(node.nodeType!==7 && node.nodeType !==8){
41544                                                 buf.push(getTextContent(node));
41545                                         }
41546                                         node = node.nextSibling;
41547                                 }
41548                                 return buf.join('');
41549                         default:
41550                                 return node.nodeValue;
41551                         }
41552                 }
41553                 __set__ = function(object,key,value){
41554                         //console.log(value)
41555                         object['$$'+key] = value;
41556                 };
41557         }
41558 }catch(e){//ie8
41559 }
41560
41561 if(typeof commonjsRequire == 'function'){
41562         exports.DOMImplementation = DOMImplementation;
41563         exports.XMLSerializer = XMLSerializer;
41564 }
41565 });
41566
41567 var domParser = createCommonjsModule(function (module, exports) {
41568 function DOMParser(options){
41569         this.options = options ||{locator:{}};
41570         
41571 }
41572 DOMParser.prototype.parseFromString = function(source,mimeType){        
41573         var options = this.options;
41574         var sax$$1 =  new XMLReader();
41575         var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
41576         var errorHandler = options.errorHandler;
41577         var locator = options.locator;
41578         var defaultNSMap = options.xmlns||{};
41579         var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
41580         if(locator){
41581                 domBuilder.setDocumentLocator(locator);
41582         }
41583         
41584         sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
41585         sax$$1.domBuilder = options.domBuilder || domBuilder;
41586         if(/\/x?html?$/.test(mimeType)){
41587                 entityMap.nbsp = '\xa0';
41588                 entityMap.copy = '\xa9';
41589                 defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
41590         }
41591         defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
41592         if(source){
41593                 sax$$1.parse(source,defaultNSMap,entityMap);
41594         }else{
41595                 sax$$1.errorHandler.error("invalid document source");
41596         }
41597         return domBuilder.document;
41598 };
41599 function buildErrorHandler(errorImpl,domBuilder,locator){
41600         if(!errorImpl){
41601                 if(domBuilder instanceof DOMHandler){
41602                         return domBuilder;
41603                 }
41604                 errorImpl = domBuilder ;
41605         }
41606         var errorHandler = {};
41607         var isCallback = errorImpl instanceof Function;
41608         locator = locator||{};
41609         function build(key){
41610                 var fn = errorImpl[key];
41611                 if(!fn && isCallback){
41612                         fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
41613                 }
41614                 errorHandler[key] = fn && function(msg){
41615                         fn('[xmldom '+key+']\t'+msg+_locator(locator));
41616                 }||function(){};
41617         }
41618         build('warning');
41619         build('error');
41620         build('fatalError');
41621         return errorHandler;
41622 }
41623
41624 //console.log('#\n\n\n\n\n\n\n####')
41625 /**
41626  * +ContentHandler+ErrorHandler
41627  * +LexicalHandler+EntityResolver2
41628  * -DeclHandler-DTDHandler 
41629  * 
41630  * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
41631  * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
41632  * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
41633  */
41634 function DOMHandler() {
41635     this.cdata = false;
41636 }
41637 function position(locator,node){
41638         node.lineNumber = locator.lineNumber;
41639         node.columnNumber = locator.columnNumber;
41640 }
41641 /**
41642  * @see org.xml.sax.ContentHandler#startDocument
41643  * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
41644  */ 
41645 DOMHandler.prototype = {
41646         startDocument : function() {
41647         this.document = new DOMImplementation().createDocument(null, null, null);
41648         if (this.locator) {
41649                 this.document.documentURI = this.locator.systemId;
41650         }
41651         },
41652         startElement:function(namespaceURI, localName, qName, attrs) {
41653                 var doc = this.document;
41654             var el = doc.createElementNS(namespaceURI, qName||localName);
41655             var len = attrs.length;
41656             appendElement(this, el);
41657             this.currentElement = el;
41658             
41659                 this.locator && position(this.locator,el);
41660             for (var i = 0 ; i < len; i++) {
41661                 var namespaceURI = attrs.getURI(i);
41662                 var value = attrs.getValue(i);
41663                 var qName = attrs.getQName(i);
41664                         var attr = doc.createAttributeNS(namespaceURI, qName);
41665                         if( attr.getOffset){
41666                                 position(attr.getOffset(1),attr);
41667                         }
41668                         attr.value = attr.nodeValue = value;
41669                         el.setAttributeNode(attr);
41670             }
41671         },
41672         endElement:function(namespaceURI, localName, qName) {
41673                 var current = this.currentElement;
41674             var tagName = current.tagName;
41675             this.currentElement = current.parentNode;
41676         },
41677         startPrefixMapping:function(prefix, uri) {
41678         },
41679         endPrefixMapping:function(prefix) {
41680         },
41681         processingInstruction:function(target, data) {
41682             var ins = this.document.createProcessingInstruction(target, data);
41683             this.locator && position(this.locator,ins);
41684             appendElement(this, ins);
41685         },
41686         ignorableWhitespace:function(ch, start, length) {
41687         },
41688         characters:function(chars, start, length) {
41689                 chars = _toString.apply(this,arguments);
41690                 //console.log(chars)
41691                 if(this.currentElement && chars){
41692                         if (this.cdata) {
41693                                 var charNode = this.document.createCDATASection(chars);
41694                                 this.currentElement.appendChild(charNode);
41695                         } else {
41696                                 var charNode = this.document.createTextNode(chars);
41697                                 this.currentElement.appendChild(charNode);
41698                         }
41699                         this.locator && position(this.locator,charNode);
41700                 }
41701         },
41702         skippedEntity:function(name) {
41703         },
41704         endDocument:function() {
41705                 this.document.normalize();
41706         },
41707         setDocumentLocator:function (locator) {
41708             if(this.locator = locator){// && !('lineNumber' in locator)){
41709                 locator.lineNumber = 0;
41710             }
41711         },
41712         //LexicalHandler
41713         comment:function(chars, start, length) {
41714                 chars = _toString.apply(this,arguments);
41715             var comm = this.document.createComment(chars);
41716             this.locator && position(this.locator,comm);
41717             appendElement(this, comm);
41718         },
41719         
41720         startCDATA:function() {
41721             //used in characters() methods
41722             this.cdata = true;
41723         },
41724         endCDATA:function() {
41725             this.cdata = false;
41726         },
41727         
41728         startDTD:function(name, publicId, systemId) {
41729                 var impl = this.document.implementation;
41730             if (impl && impl.createDocumentType) {
41731                 var dt = impl.createDocumentType(name, publicId, systemId);
41732                 this.locator && position(this.locator,dt);
41733                 appendElement(this, dt);
41734             }
41735         },
41736         /**
41737          * @see org.xml.sax.ErrorHandler
41738          * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
41739          */
41740         warning:function(error) {
41741                 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
41742         },
41743         error:function(error) {
41744                 console.error('[xmldom error]\t'+error,_locator(this.locator));
41745         },
41746         fatalError:function(error) {
41747                 console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
41748             throw error;
41749         }
41750 };
41751 function _locator(l){
41752         if(l){
41753                 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
41754         }
41755 }
41756 function _toString(chars,start,length){
41757         if(typeof chars == 'string'){
41758                 return chars.substr(start,length)
41759         }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
41760                 if(chars.length >= start+length || start){
41761                         return new java.lang.String(chars,start,length)+'';
41762                 }
41763                 return chars;
41764         }
41765 }
41766
41767 /*
41768  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
41769  * used method of org.xml.sax.ext.LexicalHandler:
41770  *  #comment(chars, start, length)
41771  *  #startCDATA()
41772  *  #endCDATA()
41773  *  #startDTD(name, publicId, systemId)
41774  *
41775  *
41776  * IGNORED method of org.xml.sax.ext.LexicalHandler:
41777  *  #endDTD()
41778  *  #startEntity(name)
41779  *  #endEntity(name)
41780  *
41781  *
41782  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
41783  * IGNORED method of org.xml.sax.ext.DeclHandler
41784  *      #attributeDecl(eName, aName, type, mode, value)
41785  *  #elementDecl(name, model)
41786  *  #externalEntityDecl(name, publicId, systemId)
41787  *  #internalEntityDecl(name, value)
41788  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
41789  * IGNORED method of org.xml.sax.EntityResolver2
41790  *  #resolveEntity(String name,String publicId,String baseURI,String systemId)
41791  *  #resolveEntity(publicId, systemId)
41792  *  #getExternalSubset(name, baseURI)
41793  * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
41794  * IGNORED method of org.xml.sax.DTDHandler
41795  *  #notationDecl(name, publicId, systemId) {};
41796  *  #unparsedEntityDecl(name, publicId, systemId, notationName) {};
41797  */
41798 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
41799         DOMHandler.prototype[key] = function(){return null};
41800 });
41801
41802 /* 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 */
41803 function appendElement (hander,node) {
41804     if (!hander.currentElement) {
41805         hander.document.appendChild(node);
41806     } else {
41807         hander.currentElement.appendChild(node);
41808     }
41809 }//appendChild and setAttributeNS are preformance key
41810
41811 if(typeof commonjsRequire == 'function'){
41812         var XMLReader = sax.XMLReader;
41813         var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
41814         exports.XMLSerializer = dom.XMLSerializer ;
41815         exports.DOMParser = DOMParser;
41816 }
41817 });
41818
41819 var togeojson = createCommonjsModule(function (module, exports) {
41820 var toGeoJSON = (function() {
41821     'use strict';
41822
41823     var removeSpace = /\s*/g,
41824         trimSpace = /^\s*|\s*$/g,
41825         splitSpace = /\s+/;
41826     // generate a short, numeric hash of a string
41827     function okhash(x) {
41828         if (!x || !x.length) return 0;
41829         for (var i = 0, h = 0; i < x.length; i++) {
41830             h = ((h << 5) - h) + x.charCodeAt(i) | 0;
41831         } return h;
41832     }
41833     // all Y children of X
41834     function get(x, y) { return x.getElementsByTagName(y); }
41835     function attr(x, y) { return x.getAttribute(y); }
41836     function attrf(x, y) { return parseFloat(attr(x, y)); }
41837     // one Y child of X, if any, otherwise null
41838     function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
41839     // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
41840     function norm(el) { if (el.normalize) { el.normalize(); } return el; }
41841     // cast array x into numbers
41842     function numarray(x) {
41843         for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); }
41844         return o;
41845     }
41846     // get the content of a text node, if any
41847     function nodeVal(x) {
41848         if (x) { norm(x); }
41849         return (x && x.textContent) || '';
41850     }
41851     // get the contents of multiple text nodes, if present
41852     function getMulti(x, ys) {
41853         var o = {}, n, k;
41854         for (k = 0; k < ys.length; k++) {
41855             n = get1(x, ys[k]);
41856             if (n) o[ys[k]] = nodeVal(n);
41857         }
41858         return o;
41859     }
41860     // add properties of Y to X, overwriting if present in both
41861     function extend(x, y) { for (var k in y) x[k] = y[k]; }
41862     // get one coordinate from a coordinate array, if any
41863     function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
41864     // get all coordinates from a coordinate array as [[],[]]
41865     function coord(v) {
41866         var coords = v.replace(trimSpace, '').split(splitSpace),
41867             o = [];
41868         for (var i = 0; i < coords.length; i++) {
41869             o.push(coord1(coords[i]));
41870         }
41871         return o;
41872     }
41873     function coordPair(x) {
41874         var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
41875             ele = get1(x, 'ele'),
41876             // handle namespaced attribute in browser
41877             heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
41878             time = get1(x, 'time'),
41879             e;
41880         if (ele) {
41881             e = parseFloat(nodeVal(ele));
41882             if (!isNaN(e)) {
41883                 ll.push(e);
41884             }
41885         }
41886         return {
41887             coordinates: ll,
41888             time: time ? nodeVal(time) : null,
41889             heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
41890         };
41891     }
41892
41893     // create a new feature collection parent object
41894     function fc() {
41895         return {
41896             type: 'FeatureCollection',
41897             features: []
41898         };
41899     }
41900
41901     var serializer;
41902     if (typeof XMLSerializer !== 'undefined') {
41903         /* istanbul ignore next */
41904         serializer = new XMLSerializer();
41905     // only require xmldom in a node environment
41906     } else if (typeof exports === 'object' && typeof process === 'object' && !process.browser) {
41907         serializer = new (domParser.XMLSerializer)();
41908     }
41909     function xml2str(str) {
41910         // IE9 will create a new XMLSerializer but it'll crash immediately.
41911         // This line is ignored because we don't run coverage tests in IE9
41912         /* istanbul ignore next */
41913         if (str.xml !== undefined) return str.xml;
41914         return serializer.serializeToString(str);
41915     }
41916
41917     var t = {
41918         kml: function(doc) {
41919
41920             var gj = fc(),
41921                 // styleindex keeps track of hashed styles in order to match features
41922                 styleIndex = {}, styleByHash = {},
41923                 // stylemapindex keeps track of style maps to expose in properties
41924                 styleMapIndex = {},
41925                 // atomic geospatial types supported by KML - MultiGeometry is
41926                 // handled separately
41927                 geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
41928                 // all root placemarks in the file
41929                 placemarks = get(doc, 'Placemark'),
41930                 styles = get(doc, 'Style'),
41931                 styleMaps = get(doc, 'StyleMap');
41932
41933             for (var k = 0; k < styles.length; k++) {
41934                 var hash = okhash(xml2str(styles[k])).toString(16);
41935                 styleIndex['#' + attr(styles[k], 'id')] = hash;
41936                 styleByHash[hash] = styles[k];
41937             }
41938             for (var l = 0; l < styleMaps.length; l++) {
41939                 styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
41940                 var pairs = get(styleMaps[l], 'Pair');
41941                 var pairsMap = {};
41942                 for (var m = 0; m < pairs.length; m++) {
41943                     pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
41944                 }
41945                 styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
41946
41947             }
41948             for (var j = 0; j < placemarks.length; j++) {
41949                 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
41950             }
41951             function kmlColor(v) {
41952                 var color, opacity;
41953                 v = v || '';
41954                 if (v.substr(0, 1) === '#') { v = v.substr(1); }
41955                 if (v.length === 6 || v.length === 3) { color = v; }
41956                 if (v.length === 8) {
41957                     opacity = parseInt(v.substr(0, 2), 16) / 255;
41958                     color = '#' + v.substr(6, 2) +
41959                         v.substr(4, 2) +
41960                         v.substr(2, 2);
41961                 }
41962                 return [color, isNaN(opacity) ? undefined : opacity];
41963             }
41964             function gxCoord(v) { return numarray(v.split(' ')); }
41965             function gxCoords(root) {
41966                 var elems = get(root, 'coord', 'gx'), coords = [], times = [];
41967                 if (elems.length === 0) elems = get(root, 'gx:coord');
41968                 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
41969                 var timeElems = get(root, 'when');
41970                 for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
41971                 return {
41972                     coords: coords,
41973                     times: times
41974                 };
41975             }
41976             function getGeometry(root) {
41977                 var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
41978                 if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); }
41979                 if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); }
41980                 if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); }
41981                 for (i = 0; i < geotypes.length; i++) {
41982                     geomNodes = get(root, geotypes[i]);
41983                     if (geomNodes) {
41984                         for (j = 0; j < geomNodes.length; j++) {
41985                             geomNode = geomNodes[j];
41986                             if (geotypes[i] === 'Point') {
41987                                 geoms.push({
41988                                     type: 'Point',
41989                                     coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
41990                                 });
41991                             } else if (geotypes[i] === 'LineString') {
41992                                 geoms.push({
41993                                     type: 'LineString',
41994                                     coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
41995                                 });
41996                             } else if (geotypes[i] === 'Polygon') {
41997                                 var rings = get(geomNode, 'LinearRing'),
41998                                     coords = [];
41999                                 for (k = 0; k < rings.length; k++) {
42000                                     coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
42001                                 }
42002                                 geoms.push({
42003                                     type: 'Polygon',
42004                                     coordinates: coords
42005                                 });
42006                             } else if (geotypes[i] === 'Track' ||
42007                                 geotypes[i] === 'gx:Track') {
42008                                 var track = gxCoords(geomNode);
42009                                 geoms.push({
42010                                     type: 'LineString',
42011                                     coordinates: track.coords
42012                                 });
42013                                 if (track.times.length) coordTimes.push(track.times);
42014                             }
42015                         }
42016                     }
42017                 }
42018                 return {
42019                     geoms: geoms,
42020                     coordTimes: coordTimes
42021                 };
42022             }
42023             function getPlacemark(root) {
42024                 var geomsAndTimes = getGeometry(root), i, properties = {},
42025                     name = nodeVal(get1(root, 'name')),
42026                     styleUrl = nodeVal(get1(root, 'styleUrl')),
42027                     description = nodeVal(get1(root, 'description')),
42028                     timeSpan = get1(root, 'TimeSpan'),
42029                     timeStamp = get1(root, 'TimeStamp'),
42030                     extendedData = get1(root, 'ExtendedData'),
42031                     lineStyle = get1(root, 'LineStyle'),
42032                     polyStyle = get1(root, 'PolyStyle'),
42033                     visibility = get1(root, 'visibility');
42034
42035                 if (!geomsAndTimes.geoms.length) return [];
42036                 if (name) properties.name = name;
42037                 if (styleUrl) {
42038                     if (styleUrl[0] !== '#') {
42039                         styleUrl = '#' + styleUrl;
42040                     }
42041
42042                     properties.styleUrl = styleUrl;
42043                     if (styleIndex[styleUrl]) {
42044                         properties.styleHash = styleIndex[styleUrl];
42045                     }
42046                     if (styleMapIndex[styleUrl]) {
42047                         properties.styleMapHash = styleMapIndex[styleUrl];
42048                         properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
42049                     }
42050                     // Try to populate the lineStyle or polyStyle since we got the style hash
42051                     var style = styleByHash[properties.styleHash];
42052                     if (style) {
42053                         if (!lineStyle) lineStyle = get1(style, 'LineStyle');
42054                         if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
42055                     }
42056                 }
42057                 if (description) properties.description = description;
42058                 if (timeSpan) {
42059                     var begin = nodeVal(get1(timeSpan, 'begin'));
42060                     var end = nodeVal(get1(timeSpan, 'end'));
42061                     properties.timespan = { begin: begin, end: end };
42062                 }
42063                 if (timeStamp) {
42064                     properties.timestamp = nodeVal(get1(timeStamp, 'when'));
42065                 }
42066                 if (lineStyle) {
42067                     var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
42068                         color = linestyles[0],
42069                         opacity = linestyles[1],
42070                         width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42071                     if (color) properties.stroke = color;
42072                     if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
42073                     if (!isNaN(width)) properties['stroke-width'] = width;
42074                 }
42075                 if (polyStyle) {
42076                     var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
42077                         pcolor = polystyles[0],
42078                         popacity = polystyles[1],
42079                         fill = nodeVal(get1(polyStyle, 'fill')),
42080                         outline = nodeVal(get1(polyStyle, 'outline'));
42081                     if (pcolor) properties.fill = pcolor;
42082                     if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
42083                     if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
42084                     if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
42085                 }
42086                 if (extendedData) {
42087                     var datas = get(extendedData, 'Data'),
42088                         simpleDatas = get(extendedData, 'SimpleData');
42089
42090                     for (i = 0; i < datas.length; i++) {
42091                         properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
42092                     }
42093                     for (i = 0; i < simpleDatas.length; i++) {
42094                         properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
42095                     }
42096                 }
42097                 if (visibility) {
42098                     properties.visibility = nodeVal(visibility);
42099                 }
42100                 if (geomsAndTimes.coordTimes.length) {
42101                     properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
42102                         geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
42103                 }
42104                 var feature = {
42105                     type: 'Feature',
42106                     geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
42107                         type: 'GeometryCollection',
42108                         geometries: geomsAndTimes.geoms
42109                     },
42110                     properties: properties
42111                 };
42112                 if (attr(root, 'id')) feature.id = attr(root, 'id');
42113                 return [feature];
42114             }
42115             return gj;
42116         },
42117         gpx: function(doc) {
42118             var i,
42119                 tracks = get(doc, 'trk'),
42120                 routes = get(doc, 'rte'),
42121                 waypoints = get(doc, 'wpt'),
42122                 // a feature collection
42123                 gj = fc(),
42124                 feature;
42125             for (i = 0; i < tracks.length; i++) {
42126                 feature = getTrack(tracks[i]);
42127                 if (feature) gj.features.push(feature);
42128             }
42129             for (i = 0; i < routes.length; i++) {
42130                 feature = getRoute(routes[i]);
42131                 if (feature) gj.features.push(feature);
42132             }
42133             for (i = 0; i < waypoints.length; i++) {
42134                 gj.features.push(getPoint(waypoints[i]));
42135             }
42136             function getPoints(node, pointname) {
42137                 var pts = get(node, pointname),
42138                     line = [],
42139                     times = [],
42140                     heartRates = [],
42141                     l = pts.length;
42142                 if (l < 2) return {};  // Invalid line in GeoJSON
42143                 for (var i = 0; i < l; i++) {
42144                     var c = coordPair(pts[i]);
42145                     line.push(c.coordinates);
42146                     if (c.time) times.push(c.time);
42147                     if (c.heartRate) heartRates.push(c.heartRate);
42148                 }
42149                 return {
42150                     line: line,
42151                     times: times,
42152                     heartRates: heartRates
42153                 };
42154             }
42155             function getTrack(node) {
42156                 var segments = get(node, 'trkseg'),
42157                     track = [],
42158                     times = [],
42159                     heartRates = [],
42160                     line;
42161                 for (var i = 0; i < segments.length; i++) {
42162                     line = getPoints(segments[i], 'trkpt');
42163                     if (line) {
42164                         if (line.line) track.push(line.line);
42165                         if (line.times && line.times.length) times.push(line.times);
42166                         if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates);
42167                     }
42168                 }
42169                 if (track.length === 0) return;
42170                 var properties = getProperties(node);
42171                 if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
42172                 if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
42173                 return {
42174                     type: 'Feature',
42175                     properties: properties,
42176                     geometry: {
42177                         type: track.length === 1 ? 'LineString' : 'MultiLineString',
42178                         coordinates: track.length === 1 ? track[0] : track
42179                     }
42180                 };
42181             }
42182             function getRoute(node) {
42183                 var line = getPoints(node, 'rtept');
42184                 if (!line.line) return;
42185                 var routeObj = {
42186                     type: 'Feature',
42187                     properties: getProperties(node),
42188                     geometry: {
42189                         type: 'LineString',
42190                         coordinates: line.line
42191                     }
42192                 };
42193                 return routeObj;
42194             }
42195             function getPoint(node) {
42196                 var prop = getProperties(node);
42197                 extend(prop, getMulti(node, ['sym', 'type']));
42198                 return {
42199                     type: 'Feature',
42200                     properties: prop,
42201                     geometry: {
42202                         type: 'Point',
42203                         coordinates: coordPair(node).coordinates
42204                     }
42205                 };
42206             }
42207             function getProperties(node) {
42208                 var prop, links;
42209                 prop = getMulti(node, ['name', 'cmt', 'desc', 'time', 'keywords']);
42210                 links = get(node, 'link');
42211                 if (links.length) prop.links = [];
42212                 for (var i = 0, link; i < links.length; i++) {
42213                     link = { href: attr(links[i], 'href') };
42214                     extend(link, getMulti(links[i], ['text', 'type']));
42215                     prop.links.push(link);
42216                 }
42217                 return prop;
42218             }
42219             return gj;
42220         }
42221     };
42222     return t;
42223 })();
42224
42225 if (typeof module !== 'undefined') module.exports = toGeoJSON;
42226 });
42227
42228 function svgGpx(projection, context, dispatch$$1) {
42229     var showLabels = true,
42230         detected = utilDetect(),
42231         layer;
42232
42233
42234     function init() {
42235         if (svgGpx.initialized) return;  // run once
42236
42237         svgGpx.geojson = {};
42238         svgGpx.enabled = true;
42239
42240         function over() {
42241             event.stopPropagation();
42242             event.preventDefault();
42243             event.dataTransfer.dropEffect = 'copy';
42244         }
42245
42246         select('body')
42247             .attr('dropzone', 'copy')
42248             .on('drop.localgpx', function() {
42249                 event.stopPropagation();
42250                 event.preventDefault();
42251                 if (!detected.filedrop) return;
42252                 drawGpx.files(event.dataTransfer.files);
42253             })
42254             .on('dragenter.localgpx', over)
42255             .on('dragexit.localgpx', over)
42256             .on('dragover.localgpx', over);
42257
42258         svgGpx.initialized = true;
42259     }
42260
42261
42262     function drawGpx(selection$$1) {
42263         var geojson = svgGpx.geojson,
42264             enabled = svgGpx.enabled;
42265
42266         layer = selection$$1.selectAll('.layer-gpx')
42267             .data(enabled ? [0] : []);
42268
42269         layer.exit()
42270             .remove();
42271
42272         layer = layer.enter()
42273             .append('g')
42274             .attr('class', 'layer-gpx')
42275             .merge(layer);
42276
42277
42278         var paths = layer
42279             .selectAll('path')
42280             .data([geojson]);
42281
42282         paths.exit()
42283             .remove();
42284
42285         paths = paths.enter()
42286             .append('path')
42287             .attr('class', 'gpx')
42288             .merge(paths);
42289
42290
42291         var path$$1 = index$5(projection);
42292
42293         paths
42294             .attr('d', path$$1);
42295
42296
42297         var labels = layer.selectAll('text')
42298             .data(showLabels && geojson.features ? geojson.features : []);
42299
42300         labels.exit()
42301             .remove();
42302
42303         labels = labels.enter()
42304             .append('text')
42305             .attr('class', 'gpx')
42306             .merge(labels);
42307
42308         labels
42309             .text(function(d) {
42310                 return d.properties.desc || d.properties.name;
42311             })
42312             .attr('x', function(d) {
42313                 var centroid = path$$1.centroid(d);
42314                 return centroid[0] + 7;
42315             })
42316             .attr('y', function(d) {
42317                 var centroid = path$$1.centroid(d);
42318                 return centroid[1];
42319             });
42320
42321     }
42322
42323
42324     function toDom(x) {
42325         return (new DOMParser()).parseFromString(x, 'text/xml');
42326     }
42327
42328
42329     drawGpx.showLabels = function(_) {
42330         if (!arguments.length) return showLabels;
42331         showLabels = _;
42332         return this;
42333     };
42334
42335
42336     drawGpx.enabled = function(_) {
42337         if (!arguments.length) return svgGpx.enabled;
42338         svgGpx.enabled = _;
42339         dispatch$$1.call('change');
42340         return this;
42341     };
42342
42343
42344     drawGpx.hasGpx = function() {
42345         var geojson = svgGpx.geojson;
42346         return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
42347     };
42348
42349
42350     drawGpx.geojson = function(gj) {
42351         if (!arguments.length) return svgGpx.geojson;
42352         if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
42353         svgGpx.geojson = gj;
42354         dispatch$$1.call('change');
42355         return this;
42356     };
42357
42358
42359     drawGpx.url = function(url) {
42360         text(url, function(err, data) {
42361             if (!err) {
42362                 drawGpx.geojson(togeojson.gpx(toDom(data)));
42363             }
42364         });
42365         return this;
42366     };
42367
42368
42369     drawGpx.files = function(fileList) {
42370         if (!fileList.length) return this;
42371         var f = fileList[0],
42372             reader = new FileReader();
42373
42374         reader.onload = function(e) {
42375             drawGpx.geojson(togeojson.gpx(toDom(e.target.result))).fitZoom();
42376         };
42377
42378         reader.readAsText(f);
42379         return this;
42380     };
42381
42382
42383     drawGpx.fitZoom = function() {
42384         if (!this.hasGpx()) return this;
42385         var geojson = svgGpx.geojson;
42386
42387         var map$$1 = context.map(),
42388             viewport = map$$1.trimmedExtent().polygon(),
42389             coords = lodash.reduce(geojson.features, function(coords, feature) {
42390                 var c = feature.geometry.coordinates;
42391                 return lodash.union(coords, feature.geometry.type === 'Point' ? [c] : c);
42392             }, []);
42393
42394         if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
42395             var extent$$1 = geoExtent$$1(bounds(geojson));
42396             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
42397         }
42398
42399         return this;
42400     };
42401
42402
42403     init();
42404     return drawGpx;
42405 }
42406
42407 function svgIcon(name, svgklass, useklass) {
42408     return function drawIcon(selection) {
42409         selection.selectAll('svg')
42410             .data([0])
42411             .enter()
42412             .append('svg')
42413             .attr('class', 'icon ' + (svgklass || ''))
42414             .append('use')
42415             .attr('xlink:href', name)
42416             .attr('class', useklass);
42417     };
42418 }
42419
42420 function svgLabels(projection, context) {
42421     var path$$1 = index$5(projection),
42422         detected = utilDetect(),
42423         baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
42424         rdrawn = index$8(),
42425         rskipped = index$8(),
42426         textWidthCache = {},
42427         entitybboxes = {};
42428
42429     // Listed from highest to lowest priority
42430     var labelStack = [
42431         ['line', 'aeroway', '*', 12],
42432         ['line', 'highway', 'motorway', 12],
42433         ['line', 'highway', 'trunk', 12],
42434         ['line', 'highway', 'primary', 12],
42435         ['line', 'highway', 'secondary', 12],
42436         ['line', 'highway', 'tertiary', 12],
42437         ['line', 'highway', '*', 12],
42438         ['line', 'railway', '*', 12],
42439         ['line', 'waterway', '*', 12],
42440         ['area', 'aeroway', '*', 12],
42441         ['area', 'amenity', '*', 12],
42442         ['area', 'building', '*', 12],
42443         ['area', 'historic', '*', 12],
42444         ['area', 'leisure', '*', 12],
42445         ['area', 'man_made', '*', 12],
42446         ['area', 'natural', '*', 12],
42447         ['area', 'shop', '*', 12],
42448         ['area', 'tourism', '*', 12],
42449         ['area', 'camp_site', '*', 12],
42450         ['point', 'aeroway', '*', 10],
42451         ['point', 'amenity', '*', 10],
42452         ['point', 'building', '*', 10],
42453         ['point', 'historic', '*', 10],
42454         ['point', 'leisure', '*', 10],
42455         ['point', 'man_made', '*', 10],
42456         ['point', 'natural', '*', 10],
42457         ['point', 'shop', '*', 10],
42458         ['point', 'tourism', '*', 10],
42459         ['point', 'camp_site', '*', 10],
42460         ['line', 'name', '*', 12],
42461         ['area', 'name', '*', 12],
42462         ['point', 'name', '*', 10]
42463     ];
42464
42465
42466     function blacklisted(preset) {
42467         var noIcons = ['building', 'landuse', 'natural'];
42468         return lodash.some(noIcons, function(s) {
42469             return preset.id.indexOf(s) >= 0;
42470         });
42471     }
42472
42473
42474     function get(array, prop) {
42475         return function(d, i) { return array[i][prop]; };
42476     }
42477
42478
42479     function textWidth(text$$1, size, elem) {
42480         var c = textWidthCache[size];
42481         if (!c) c = textWidthCache[size] = {};
42482
42483         if (c[text$$1]) {
42484             return c[text$$1];
42485
42486         } else if (elem) {
42487             c[text$$1] = elem.getComputedTextLength();
42488             return c[text$$1];
42489
42490         } else {
42491             var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
42492             if (str === null) {
42493                 return size / 3 * 2 * text$$1.length;
42494             } else {
42495                 return size / 3 * (2 * text$$1.length + str.length);
42496             }
42497         }
42498     }
42499
42500
42501     function drawLinePaths(selection$$1, entities, filter, classes, labels) {
42502         var paths = selection$$1.selectAll('path')
42503             .filter(filter)
42504             .data(entities, osmEntity$$1.key);
42505
42506         paths.exit()
42507             .remove();
42508
42509         paths.enter()
42510             .append('path')
42511             .style('stroke-width', get(labels, 'font-size'))
42512             .attr('id', function(d) { return 'labelpath-' + d.id; })
42513             .attr('class', classes)
42514             .merge(paths)
42515             .attr('d', get(labels, 'lineString'));
42516     }
42517
42518
42519     function drawLineLabels(selection$$1, entities, filter, classes, labels) {
42520         var texts = selection$$1.selectAll('text.' + classes)
42521             .filter(filter)
42522             .data(entities, osmEntity$$1.key);
42523
42524         texts.exit()
42525             .remove();
42526
42527         texts.enter()
42528             .append('text')
42529             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
42530             .attr('dy', baselineHack ? '0.35em' : null)
42531             .append('textPath')
42532             .attr('class', 'textpath');
42533
42534         texts = selection$$1.selectAll('text.' + classes);
42535
42536         texts.selectAll('.textpath')
42537             .filter(filter)
42538             .data(entities, osmEntity$$1.key)
42539             .attr('startOffset', '50%')
42540             .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
42541             .text(utilDisplayName);
42542     }
42543
42544
42545     function drawPointLabels(selection$$1, entities, filter, classes, labels) {
42546         var texts = selection$$1.selectAll('text.' + classes)
42547             .filter(filter)
42548             .data(entities, osmEntity$$1.key);
42549
42550         texts.exit()
42551             .remove();
42552
42553         texts = texts.enter()
42554             .append('text')
42555             .attr('class', function(d, i) {
42556                 return classes + ' ' + labels[i].classes + ' ' + d.id;
42557             })
42558             .merge(texts);
42559
42560         texts
42561             .attr('x', get(labels, 'x'))
42562             .attr('y', get(labels, 'y'))
42563             .style('text-anchor', get(labels, 'textAnchor'))
42564             .text(utilDisplayName)
42565             .each(function(d, i) {
42566                 textWidth(utilDisplayName(d), labels[i].height, this);
42567             });
42568     }
42569
42570
42571     function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
42572         entities = entities.filter(hasText);
42573         labels = labels.filter(hasText);
42574         drawPointLabels(selection$$1, entities, filter, classes, labels);
42575
42576         function hasText(d, i) {
42577             return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
42578         }
42579     }
42580
42581
42582     function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
42583         var icons = selection$$1.selectAll('use')
42584             .filter(filter)
42585             .data(entities, osmEntity$$1.key);
42586
42587         icons.exit()
42588             .remove();
42589
42590         icons = icons.enter()
42591             .append('use')
42592             .attr('class', 'icon areaicon')
42593             .attr('width', '18px')
42594             .attr('height', '18px')
42595             .merge(icons);
42596
42597         icons
42598             .attr('transform', get(labels, 'transform'))
42599             .attr('xlink:href', function(d) {
42600                 var icon = context.presets().match(d, context.graph()).icon;
42601                 return '#' + icon + (icon === 'hairdresser' ? '-24': '-18');    // workaround: maki hairdresser-18 broken?
42602             });
42603     }
42604
42605
42606     function drawCollisionBoxes(selection$$1, rtree, which) {
42607         var showDebug = context.getDebug('collision'),
42608             classes = 'debug ' + which + ' ' +
42609                 (which === 'debug-skipped' ? 'orange' : 'yellow');
42610
42611         var debug = selection$$1.selectAll('.layer-label-debug')
42612                 .data(showDebug ? [true] : []);
42613
42614         debug.exit()
42615             .remove();
42616
42617         debug = debug.enter()
42618             .append('g')
42619             .attr('class', 'layer-label-debug')
42620             .merge(debug);
42621
42622         if (showDebug) {
42623             var gj = rtree.all().map(function(d) {
42624                 return { type: 'Polygon', coordinates: [[
42625                     [d.minX, d.minY],
42626                     [d.maxX, d.minY],
42627                     [d.maxX, d.maxY],
42628                     [d.minX, d.maxY],
42629                     [d.minX, d.minY]
42630                 ]]};
42631             });
42632
42633             var debugboxes = debug.selectAll('.' + which)
42634                 .data(gj);
42635
42636             debugboxes.exit()
42637                 .remove();
42638
42639             debugboxes = debugboxes.enter()
42640                 .append('path')
42641                 .attr('class', classes)
42642                 .merge(debugboxes);
42643
42644             debugboxes
42645                 .attr('d', index$5());
42646         }
42647     }
42648
42649
42650     function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
42651         var hidePoints = !selection$$1.selectAll('.node.point').node();
42652
42653         var labelable = [], i, j, k, entity;
42654         for (i = 0; i < labelStack.length; i++) {
42655             labelable.push([]);
42656         }
42657
42658         if (fullRedraw) {
42659             rdrawn.clear();
42660             rskipped.clear();
42661             entitybboxes = {};
42662         } else {
42663             for (i = 0; i < entities.length; i++) {
42664                 entity = entities[i];
42665                 var toRemove = []
42666                     .concat(entitybboxes[entity.id] || [])
42667                     .concat(entitybboxes[entity.id + 'I'] || []);
42668
42669                 for (j = 0; j < toRemove.length; j++) {
42670                     rdrawn.remove(toRemove[j]);
42671                     rskipped.remove(toRemove[j]);
42672                 }
42673             }
42674         }
42675
42676         // Split entities into groups specified by labelStack
42677         for (i = 0; i < entities.length; i++) {
42678             entity = entities[i];
42679             var geometry = entity.geometry(graph);
42680
42681             if (geometry === 'vertex')
42682                 continue;
42683             if (hidePoints && geometry === 'point')
42684                 continue;
42685
42686             var preset = geometry === 'area' && context.presets().match(entity, graph),
42687                 icon = preset && !blacklisted(preset) && preset.icon;
42688
42689             if (!icon && !utilDisplayName(entity))
42690                 continue;
42691
42692             for (k = 0; k < labelStack.length; k++) {
42693                 var matchGeom = labelStack[k][0],
42694                     matchKey = labelStack[k][1],
42695                     matchVal = labelStack[k][2],
42696                     hasVal = entity.tags[matchKey];
42697
42698                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
42699                     labelable[k].push(entity);
42700                     break;
42701                 }
42702             }
42703         }
42704
42705         var positions = {
42706             point: [],
42707             line: [],
42708             area: []
42709         };
42710
42711         var labelled = {
42712             point: [],
42713             line: [],
42714             area: []
42715         };
42716
42717         // Try and find a valid label for labellable entities
42718         for (k = 0; k < labelable.length; k++) {
42719             var fontSize = labelStack[k][3];
42720             for (i = 0; i < labelable[k].length; i++) {
42721                 entity = labelable[k][i];
42722                 var name = utilDisplayName(entity),
42723                     width = name && textWidth(name, fontSize),
42724                     p;
42725                 if (entity.geometry(graph) === 'point') {
42726                     p = getPointLabel(entity, width, fontSize);
42727                 } else if (entity.geometry(graph) === 'line') {
42728                     p = getLineLabel(entity, width, fontSize);
42729                 } else if (entity.geometry(graph) === 'area') {
42730                     p = getAreaLabel(entity, width, fontSize);
42731                 }
42732                 if (p) {
42733                     p.classes = entity.geometry(graph) + ' tag-' + labelStack[k][1];
42734                     positions[entity.geometry(graph)].push(p);
42735                     labelled[entity.geometry(graph)].push(entity);
42736                 }
42737             }
42738         }
42739
42740
42741         function getPointLabel(entity, width, height) {
42742             var pointOffsets = {
42743                     ltr: [15, -12, 'start'],
42744                     rtl: [-15, -12, 'end']
42745                 };
42746
42747             var coord = projection(entity.loc),
42748                 margin = 2,
42749                 textDirection = detected.textDirection,
42750                 offset = pointOffsets[textDirection],
42751                 p = {
42752                     height: height,
42753                     width: width,
42754                     x: coord[0] + offset[0],
42755                     y: coord[1] + offset[1],
42756                     textAnchor: offset[2]
42757                 },
42758                 bbox;
42759
42760             if (textDirection === 'rtl') {
42761                 bbox = {
42762                     minX: p.x - width - margin,
42763                     minY: p.y - (height / 2) - margin,
42764                     maxX: p.x + margin,
42765                     maxY: p.y + (height / 2) + margin
42766                 };
42767             } else {
42768                 bbox = {
42769                     minX: p.x - margin,
42770                     minY: p.y - (height / 2) - margin,
42771                     maxX: p.x + width + margin,
42772                     maxY: p.y + (height / 2) + margin
42773                 };
42774             }
42775
42776             if (tryInsert([bbox], entity.id, true)) {
42777                 return p;
42778             }
42779         }
42780
42781
42782         function getLineLabel(entity, width, height) {
42783             var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
42784                 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
42785                 length = geoPathLength(nodes);
42786
42787             if (length < width + 20) return;
42788
42789             // % along the line to attempt to place the label
42790             var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
42791                                25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
42792             var margin = 3;
42793
42794             for (var i = 0; i < lineOffsets.length; i++) {
42795                 var offset = lineOffsets[i],
42796                     middle = offset / 100 * length,
42797                     start = middle - width / 2;
42798
42799                 if (start < 0 || start + width > length) continue;
42800
42801                 // generate subpath and ignore paths that are invalid or don't cross viewport.
42802                 var sub = subpath(nodes, start, start + width);
42803                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
42804                     continue;
42805                 }
42806
42807                 var isReverse = reverse(sub);
42808                 if (isReverse) {
42809                     sub = sub.reverse();
42810                 }
42811
42812                 var bboxes = [],
42813                     boxsize = (height + 2) / 2;
42814
42815                 for (var j = 0; j < sub.length - 1; j++) {
42816                     var a = sub[j];
42817                     var b = sub[j + 1];
42818                     var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
42819
42820                     for (var box = 0; box < num; box++) {
42821                         var p = geoInterp(a, b, box / num);
42822                         var x0 = p[0] - boxsize - margin;
42823                         var y0 = p[1] - boxsize - margin;
42824                         var x1 = p[0] + boxsize + margin;
42825                         var y1 = p[1] + boxsize + margin;
42826
42827                         bboxes.push({
42828                             minX: Math.min(x0, x1),
42829                             minY: Math.min(y0, y1),
42830                             maxX: Math.max(x0, x1),
42831                             maxY: Math.max(y0, y1)
42832                         });
42833                     }
42834                 }
42835
42836                 if (tryInsert(bboxes, entity.id, false)) {
42837                     return {
42838                         'font-size': height + 2,
42839                         lineString: lineString(sub),
42840                         startOffset: offset + '%'
42841                     };
42842                 }
42843             }
42844
42845             function reverse(p) {
42846                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
42847                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
42848             }
42849
42850             function lineString(nodes) {
42851                 return 'M' + nodes.join('L');
42852             }
42853
42854             function subpath(nodes, from, to) {
42855                 var sofar = 0,
42856                     start, end, i0, i1;
42857
42858                 for (var i = 0; i < nodes.length - 1; i++) {
42859                     var a = nodes[i],
42860                         b = nodes[i + 1];
42861                     var current = geoEuclideanDistance(a, b);
42862                     var portion;
42863                     if (!start && sofar + current >= from) {
42864                         portion = (from - sofar) / current;
42865                         start = [
42866                             a[0] + portion * (b[0] - a[0]),
42867                             a[1] + portion * (b[1] - a[1])
42868                         ];
42869                         i0 = i + 1;
42870                     }
42871                     if (!end && sofar + current >= to) {
42872                         portion = (to - sofar) / current;
42873                         end = [
42874                             a[0] + portion * (b[0] - a[0]),
42875                             a[1] + portion * (b[1] - a[1])
42876                         ];
42877                         i1 = i + 1;
42878                     }
42879                     sofar += current;
42880                 }
42881
42882                 var ret = nodes.slice(i0, i1);
42883                 ret.unshift(start);
42884                 ret.push(end);
42885                 return ret;
42886             }
42887         }
42888
42889
42890         function getAreaLabel(entity, width, height) {
42891             var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
42892                 extent$$1 = entity.extent(graph),
42893                 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
42894
42895             if (isNaN(centroid[0]) || entitywidth < 20) return;
42896
42897             var iconSize = 18,
42898                 iconX = centroid[0] - (iconSize / 2),
42899                 iconY = centroid[1] - (iconSize / 2),
42900                 margin = 2,
42901                 textOffset = iconSize + margin,
42902                 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
42903
42904             var bbox = {
42905                 minX: iconX,
42906                 minY: iconY,
42907                 maxX: iconX + iconSize,
42908                 maxY: iconY + iconSize
42909             };
42910
42911             // try to add icon
42912             if (tryInsert([bbox], entity.id + 'I', true)) {
42913                 if (width && entitywidth >= width + 20) {
42914                     var labelX = centroid[0],
42915                         labelY = centroid[1] + textOffset;
42916
42917                     bbox = {
42918                         minX: labelX - (width / 2) - margin,
42919                         minY: labelY - (height / 2) - margin,
42920                         maxX: labelX + (width / 2) + margin,
42921                         maxY: labelY + (height / 2) + margin
42922                     };
42923
42924                     // try to add label
42925                     if (tryInsert([bbox], entity.id, true)) {
42926                         p.x = labelX;
42927                         p.y = labelY;
42928                         p.textAnchor = 'middle';
42929                         p.height = height;
42930                     }
42931                 }
42932
42933                 return p;
42934             }
42935         }
42936
42937
42938         function tryInsert(bboxes, id, saveSkipped) {
42939             var skipped = false,
42940                 bbox;
42941
42942             for (var i = 0; i < bboxes.length; i++) {
42943                 bbox = bboxes[i];
42944                 bbox.id = id;
42945
42946                 // Check that label is visible
42947                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
42948                     skipped = true;
42949                     break;
42950                 }
42951                 if (rdrawn.collides(bbox)) {
42952                     skipped = true;
42953                     break;
42954                 }
42955             }
42956
42957             entitybboxes[id] = bboxes;
42958
42959             if (skipped) {
42960                 if (saveSkipped) {
42961                     rskipped.load(bboxes);
42962                 }
42963             } else {
42964                 rdrawn.load(bboxes);
42965             }
42966
42967             return !skipped;
42968         }
42969
42970
42971         var label = selection$$1.selectAll('.layer-label'),
42972             halo = selection$$1.selectAll('.layer-halo');
42973
42974         // points
42975         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
42976         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
42977
42978         // lines
42979         drawLinePaths(halo, labelled.line, filter, '', positions.line);
42980         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
42981         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
42982
42983         // areas
42984         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
42985         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
42986         drawAreaIcons(label, labelled.area, filter, 'arealabel-icon', positions.area);
42987
42988         // debug
42989         drawCollisionBoxes(label, rskipped, 'debug-skipped');
42990         drawCollisionBoxes(label, rdrawn, 'debug-drawn');
42991     }
42992
42993
42994     function hideOnMouseover() {
42995         if (event.buttons) return;
42996
42997         var layers = select(this)
42998             .selectAll('.layer-label, .layer-halo');
42999
43000         layers.selectAll('.proximate')
43001             .classed('proximate', false);
43002
43003         var mouse$$1 = context.mouse(),
43004             pad = 20,
43005             bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad },
43006             ids = lodash.map(rdrawn.search(bbox), 'id');
43007
43008         layers.selectAll(utilEntitySelector(ids))
43009             .classed('proximate', true);
43010     }
43011
43012
43013     drawLabels.observe = function(selection$$1) {
43014         selection$$1.on('mousemove.hidelabels', hideOnMouseover);
43015     };
43016
43017
43018     drawLabels.off = function(selection$$1) {
43019         selection$$1.on('mousemove.hidelabels', null);
43020     };
43021
43022
43023     return drawLabels;
43024 }
43025
43026 // Copies a variable number of methods from source to target.
43027 function utilRebind(target, source) {
43028     var i = 1, n = arguments.length, method;
43029     while (++i < n) {
43030         target[method = arguments[i]] = d3_rebind(target, source, source[method]);
43031     }
43032     return target;
43033 }
43034
43035 // Method is assumed to be a standard D3 getter-setter:
43036 // If passed with no arguments, gets the value.
43037 // If passed with arguments, sets the value and returns the target.
43038 function d3_rebind(target, source, method) {
43039     return function() {
43040         var value = method.apply(source, arguments);
43041         return value === source ? target : value;
43042     };
43043 }
43044
43045 function refresh(selection, node) {
43046     var cr = node.getBoundingClientRect();
43047     var prop = [cr.width, cr.height];
43048     selection.property('__dimensions__', prop);
43049     return prop;
43050 }
43051
43052 function utilGetDimensions(selection, force) {
43053     if (!selection || selection.empty()) {
43054         return [0, 0];
43055     }
43056     var node = selection.node(),
43057         cached = selection.property('__dimensions__');
43058     return (!cached || force) ? refresh(selection, node) : cached;
43059 }
43060
43061
43062 function utilSetDimensions(selection, dimensions) {
43063     if (!selection || selection.empty()) {
43064         return selection;
43065     }
43066     var node = selection.node();
43067     if (dimensions === null) {
43068         refresh(selection, node);
43069         return selection;
43070     }
43071     return selection
43072         .property('__dimensions__', [dimensions[0], dimensions[1]])
43073         .attr('width', dimensions[0])
43074         .attr('height', dimensions[1]);
43075 }
43076
43077 function svgPointTransform(projection) {
43078     return function(entity) {
43079         // http://jsperf.com/short-array-join
43080         var pt = projection(entity.loc);
43081         return 'translate(' + pt[0] + ',' + pt[1] + ')';
43082     };
43083 }
43084
43085 function d3geoTile() {
43086   var size = [960, 500],
43087       scale = 256,
43088       scaleExtent = [0, 20],
43089       translate = [size[0] / 2, size[1] / 2],
43090       zoomDelta = 0;
43091
43092   function bound(_) {
43093       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43094   }
43095
43096   function tile() {
43097     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43098         z0 = bound(Math.round(z + zoomDelta)),
43099         k = Math.pow(2, z - z0 + 8),
43100         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43101         tiles = [],
43102         cols = range(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43103         rows = range(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43104
43105     rows.forEach(function(y) {
43106       cols.forEach(function(x) {
43107         tiles.push([x, y, z0]);
43108       });
43109     });
43110
43111     tiles.translate = origin;
43112     tiles.scale = k;
43113
43114     return tiles;
43115   }
43116
43117   tile.scaleExtent = function(_) {
43118     if (!arguments.length) return scaleExtent;
43119     scaleExtent = _;
43120     return tile;
43121   };
43122
43123   tile.size = function(_) {
43124     if (!arguments.length) return size;
43125     size = _;
43126     return tile;
43127   };
43128
43129   tile.scale = function(_) {
43130     if (!arguments.length) return scale;
43131     scale = _;
43132     return tile;
43133   };
43134
43135   tile.translate = function(_) {
43136     if (!arguments.length) return translate;
43137     translate = _;
43138     return tile;
43139   };
43140
43141   tile.zoomDelta = function(_) {
43142     if (!arguments.length) return zoomDelta;
43143     zoomDelta = +_;
43144     return tile;
43145   };
43146
43147   return tile;
43148 }
43149
43150 /* global Mapillary:false */
43151 var apibase = 'https://a.mapillary.com/v2/';
43152 var viewercss = 'mapillary-js/mapillary.min.css';
43153 var viewerjs = 'mapillary-js/mapillary.min.js';
43154 var trafficocss = 'traffico/stylesheets/traffico.css';
43155 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43156 var maxResults = 1000;
43157 var tileZoom = 14;
43158 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43159 var mapillaryCache;
43160 var mapillaryClicks;
43161 var mapillaryImage;
43162 var mapillarySignDefs;
43163 var mapillaryViewer;
43164
43165
43166 function abortRequest(i) {
43167     i.abort();
43168 }
43169
43170
43171 function nearNullIsland(x, y, z) {
43172     if (z >= 7) {
43173         var center = Math.pow(2, z - 1),
43174             width = Math.pow(2, z - 6),
43175             min$$1 = center - (width / 2),
43176             max$$1 = center + (width / 2) - 1;
43177         return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43178     }
43179     return false;
43180 }
43181
43182
43183 function maxPageAtZoom(z) {
43184     if (z < 15)   return 2;
43185     if (z === 15) return 5;
43186     if (z === 16) return 10;
43187     if (z === 17) return 20;
43188     if (z === 18) return 40;
43189     if (z > 18)   return 80;
43190 }
43191
43192
43193 function getTiles(projection) {
43194     var s = projection.scale() * 2 * Math.PI,
43195         z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43196         ts = 256 * Math.pow(2, z - tileZoom),
43197         origin = [
43198             s / 2 - projection.translate()[0],
43199             s / 2 - projection.translate()[1]];
43200
43201     return d3geoTile()
43202         .scaleExtent([tileZoom, tileZoom])
43203         .scale(s)
43204         .size(projection.clipExtent()[1])
43205         .translate(projection.translate())()
43206         .map(function(tile) {
43207             var x = tile[0] * ts - origin[0],
43208                 y = tile[1] * ts - origin[1];
43209
43210             return {
43211                 id: tile.toString(),
43212                 xyz: tile,
43213                 extent: geoExtent$$1(
43214                     projection.invert([x, y + ts]),
43215                     projection.invert([x + ts, y])
43216                 )
43217             };
43218         });
43219 }
43220
43221
43222 function loadTiles(which, url, projection) {
43223     var s = projection.scale() * 2 * Math.PI,
43224         currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
43225
43226     var tiles = getTiles(projection).filter(function(t) {
43227             return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
43228         });
43229
43230     lodash.filter(which.inflight, function(v, k) {
43231         var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
43232         if (!wanted) delete which.inflight[k];
43233         return !wanted;
43234     }).map(abortRequest);
43235
43236     tiles.forEach(function(tile) {
43237         loadNextTilePage(which, currZoom, url, tile);
43238     });
43239 }
43240
43241
43242 function loadNextTilePage(which, currZoom, url, tile) {
43243     var cache = mapillaryCache[which],
43244         rect = tile.extent.rectangle(),
43245         maxPages = maxPageAtZoom(currZoom),
43246         nextPage = cache.nextPage[tile.id] || 0;
43247
43248     if (nextPage > maxPages) return;
43249
43250     var id = tile.id + ',' + String(nextPage);
43251     if (cache.loaded[id] || cache.inflight[id]) return;
43252
43253     cache.inflight[id] = json(url +
43254         utilQsString({
43255             geojson: 'true',
43256             limit: maxResults,
43257             page: nextPage,
43258             client_id: clientId,
43259             min_lon: rect[0],
43260             min_lat: rect[1],
43261             max_lon: rect[2],
43262             max_lat: rect[3]
43263         }), function(err, data) {
43264             cache.loaded[id] = true;
43265             delete cache.inflight[id];
43266             if (err || !data.features || !data.features.length) return;
43267
43268             var features = [],
43269                 feature, loc, d;
43270
43271             for (var i = 0; i < data.features.length; i++) {
43272                 feature = data.features[i];
43273                 loc = feature.geometry.coordinates;
43274                 d = { key: feature.properties.key, loc: loc };
43275                 if (which === 'images') d.ca = feature.properties.ca;
43276                 if (which === 'signs') d.signs = feature.properties.rects;
43277
43278                 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
43279             }
43280
43281             cache.rtree.load(features);
43282
43283             if (which === 'images') dispatch$2.call('loadedImages');
43284             if (which === 'signs') dispatch$2.call('loadedSigns');
43285
43286             if (data.features.length === maxResults) {  // more pages to load
43287                 cache.nextPage[tile.id] = nextPage + 1;
43288                 loadNextTilePage(which, currZoom, url, tile);
43289             } else {
43290                 cache.nextPage[tile.id] = Infinity;     // no more pages to load
43291             }
43292         }
43293     );
43294 }
43295
43296
43297 // partition viewport into `psize` x `psize` regions
43298 function partitionViewport(psize, projection) {
43299     var dimensions = projection.clipExtent()[1];
43300     psize = psize || 16;
43301     var cols = range(0, dimensions[0], psize),
43302         rows = range(0, dimensions[1], psize),
43303         partitions = [];
43304
43305     rows.forEach(function(y) {
43306         cols.forEach(function(x) {
43307             var min$$1 = [x, y + psize],
43308                 max$$1 = [x + psize, y];
43309             partitions.push(
43310                 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
43311         });
43312     });
43313
43314     return partitions;
43315 }
43316
43317
43318 // no more than `limit` results per partition.
43319 function searchLimited(psize, limit, projection, rtree) {
43320     limit = limit || 3;
43321
43322     var partitions = partitionViewport(psize, projection);
43323     return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
43324         return rtree.search(extent$$1.bbox())
43325             .slice(0, limit)
43326             .map(function(d) { return d.data; });
43327     })));
43328 }
43329
43330
43331
43332 var serviceMapillary = {
43333
43334     init: function() {
43335         if (!mapillaryCache) {
43336             this.reset();
43337         }
43338
43339         this.event = utilRebind(this, dispatch$2, 'on');
43340     },
43341
43342     reset: function() {
43343         var cache = mapillaryCache;
43344
43345         if (cache) {
43346             if (cache.images && cache.images.inflight) {
43347                 lodash.forEach(cache.images.inflight, abortRequest);
43348             }
43349             if (cache.signs && cache.signs.inflight) {
43350                 lodash.forEach(cache.signs.inflight, abortRequest);
43351             }
43352         }
43353
43354         mapillaryCache = {
43355             images: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$8() },
43356             signs:  { inflight: {}, loaded: {}, nextPage: {}, rtree: index$8() }
43357         };
43358
43359         mapillaryImage = null;
43360         mapillaryClicks = [];
43361     },
43362
43363
43364     images: function(projection) {
43365         var psize = 16, limit = 3;
43366         return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
43367     },
43368
43369
43370     signs: function(projection) {
43371         var psize = 32, limit = 3;
43372         return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
43373     },
43374
43375
43376     signsSupported: function() {
43377         var detected = utilDetect();
43378         if (detected.ie) return false;
43379         if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
43380         return true;
43381     },
43382
43383
43384     signHTML: function(d) {
43385         if (!mapillarySignDefs) return;
43386
43387         var detectionPackage = d.signs[0].package,
43388             type = d.signs[0].type,
43389             country = detectionPackage.split('_')[1];
43390
43391         return mapillarySignDefs[country][type];
43392     },
43393
43394
43395     loadImages: function(projection) {
43396         var url = apibase + 'search/im/geojson?';
43397         loadTiles('images', url, projection);
43398     },
43399
43400
43401     loadSigns: function(context, projection) {
43402         var url = apibase + 'search/im/geojson/or?';
43403         loadTiles('signs', url, projection);
43404
43405         // load traffico css
43406         select('head').selectAll('#traffico')
43407             .data([0])
43408             .enter()
43409             .append('link')
43410             .attr('id', 'traffico')
43411             .attr('rel', 'stylesheet')
43412             .attr('href', context.asset(trafficocss));
43413
43414         // load traffico sign defs
43415         if (!mapillarySignDefs) {
43416             mapillarySignDefs = {};
43417             lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
43418                 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
43419                     if (err) return;
43420                     if (region === 'de') region = 'eu';
43421                     mapillarySignDefs[region] = data;
43422                 });
43423             });
43424         }
43425     },
43426
43427
43428     loadViewer: function(context) {
43429         var that = this;
43430         var wrap = select('#content').selectAll('.mapillary-wrap')
43431             .data([0]);
43432
43433         var enter = wrap.enter()
43434             .append('div')
43435             .attr('class', 'mapillary-wrap')
43436             .classed('al', true)       // 'al'=left,  'ar'=right
43437             .classed('hidden', true);
43438
43439         enter
43440             .append('button')
43441             .attr('class', 'thumb-hide')
43442             .on('click', function () { that.hideViewer(); })
43443             .append('div')
43444             .call(svgIcon('#icon-close'));
43445
43446         enter
43447             .append('div')
43448             .attr('id', 'mly')
43449             .attr('class', 'mly-wrapper')
43450             .classed('active', false);
43451
43452         // load mapillary-viewercss
43453         select('head').selectAll('#mapillary-viewercss')
43454             .data([0])
43455             .enter()
43456             .append('link')
43457             .attr('id', 'mapillary-viewercss')
43458             .attr('rel', 'stylesheet')
43459             .attr('href', context.asset(viewercss));
43460
43461         // load mapillary-viewerjs
43462         select('head').selectAll('#mapillary-viewerjs')
43463             .data([0])
43464             .enter()
43465             .append('script')
43466             .attr('id', 'mapillary-viewerjs')
43467             .attr('src', context.asset(viewerjs));
43468     },
43469
43470
43471     showViewer: function() {
43472         select('#content')
43473             .selectAll('.mapillary-wrap')
43474             .classed('hidden', false)
43475             .selectAll('.mly-wrapper')
43476             .classed('active', true);
43477
43478         return this;
43479     },
43480
43481
43482     hideViewer: function() {
43483         select('#content')
43484             .selectAll('.mapillary-wrap')
43485             .classed('hidden', true)
43486             .selectAll('.mly-wrapper')
43487             .classed('active', false);
43488
43489         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
43490             .classed('selected', false);
43491
43492         mapillaryImage = null;
43493         return this;
43494     },
43495
43496
43497     updateViewer: function(imageKey, context) {
43498         if (!imageKey) return;
43499
43500         if (!mapillaryViewer) {
43501             this.initViewer(imageKey, context);
43502         } else {
43503             mapillaryViewer.moveToKey(imageKey);
43504         }
43505
43506         return this;
43507     },
43508
43509
43510     initViewer: function(imageKey, context) {
43511         var that = this;
43512         if (Mapillary && imageKey) {
43513             var opts = {
43514                 baseImageSize: 320,
43515                 component: {
43516                     cover: false,
43517                     keyboard: false
43518                 }
43519             };
43520
43521             mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
43522             mapillaryViewer.on('nodechanged', nodeChanged);
43523         }
43524
43525         function nodeChanged(node) {
43526             var clicks = mapillaryClicks;
43527             var index = clicks.indexOf(node.key);
43528             if (index > -1) {    // nodechange initiated from clicking on a marker..
43529                 clicks.splice(index, 1);
43530             } else {             // nodechange initiated from the Mapillary viewer controls..
43531                 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
43532                 context.map().centerEase(loc);
43533                 that.selectedImage(node.key, false);
43534             }
43535         }
43536     },
43537
43538
43539     selectedImage: function(imageKey, fromClick) {
43540         if (!arguments.length) return mapillaryImage;
43541
43542         mapillaryImage = imageKey;
43543         if (fromClick) {
43544             mapillaryClicks.push(imageKey);
43545         }
43546
43547         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
43548             .classed('selected', function(d) { return d.key === imageKey; });
43549
43550         return this;
43551     },
43552
43553
43554     cache: function(_) {
43555         if (!arguments.length) return mapillaryCache;
43556         mapillaryCache = _;
43557         return this;
43558     },
43559
43560
43561     signDefs: function(_) {
43562         if (!arguments.length) return mapillarySignDefs;
43563         mapillarySignDefs = _;
43564         return this;
43565     }
43566
43567 };
43568
43569 var endpoint = 'https://nominatim.openstreetmap.org/reverse?';
43570 var nominatimCache;
43571
43572
43573 var serviceNominatim = {
43574
43575     init: function() { nominatimCache = index$8(); },
43576     reset: function() { nominatimCache = index$8(); },
43577
43578
43579     countryCode: function (location, callback) {
43580         var countryCodes = nominatimCache.search(
43581             { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
43582         );
43583
43584         if (countryCodes.length > 0) {
43585             return callback(null, countryCodes[0].data);
43586         }
43587
43588         json(endpoint +
43589             utilQsString({
43590                 format: 'json',
43591                 addressdetails: 1,
43592                 lat: location[1],
43593                 lon: location[0]
43594             }), function(err, result) {
43595                 if (err)
43596                     return callback(err);
43597                 else if (result && result.error)
43598                     return callback(result.error);
43599
43600                 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
43601                 nominatimCache.insert(Object.assign(extent$$1.bbox(),
43602                     { data: result.address.country_code }
43603                 ));
43604
43605                 callback(null, result.address.country_code);
43606             }
43607         );
43608     }
43609
43610 };
43611
43612 var hashes$1 = createCommonjsModule(function (module, exports) {
43613 /**
43614  * jshashes - https://github.com/h2non/jshashes
43615  * Released under the "New BSD" license
43616  *
43617  * Algorithms specification:
43618  *
43619  * MD5 - http://www.ietf.org/rfc/rfc1321.txt
43620  * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
43621  * SHA1   - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43622  * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43623  * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43624  * HMAC - http://www.ietf.org/rfc/rfc2104.txt
43625  */
43626 (function() {
43627   var Hashes;
43628
43629   function utf8Encode(str) {
43630     var x, y, output = '',
43631       i = -1,
43632       l;
43633
43634     if (str && str.length) {
43635       l = str.length;
43636       while ((i += 1) < l) {
43637         /* Decode utf-16 surrogate pairs */
43638         x = str.charCodeAt(i);
43639         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
43640         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
43641           x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
43642           i += 1;
43643         }
43644         /* Encode output as utf-8 */
43645         if (x <= 0x7F) {
43646           output += String.fromCharCode(x);
43647         } else if (x <= 0x7FF) {
43648           output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
43649             0x80 | (x & 0x3F));
43650         } else if (x <= 0xFFFF) {
43651           output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
43652             0x80 | ((x >>> 6) & 0x3F),
43653             0x80 | (x & 0x3F));
43654         } else if (x <= 0x1FFFFF) {
43655           output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
43656             0x80 | ((x >>> 12) & 0x3F),
43657             0x80 | ((x >>> 6) & 0x3F),
43658             0x80 | (x & 0x3F));
43659         }
43660       }
43661     }
43662     return output;
43663   }
43664
43665   function utf8Decode(str) {
43666     var i, ac, c1, c2, c3, arr = [],
43667       l;
43668     i = ac = c1 = c2 = c3 = 0;
43669
43670     if (str && str.length) {
43671       l = str.length;
43672       str += '';
43673
43674       while (i < l) {
43675         c1 = str.charCodeAt(i);
43676         ac += 1;
43677         if (c1 < 128) {
43678           arr[ac] = String.fromCharCode(c1);
43679           i += 1;
43680         } else if (c1 > 191 && c1 < 224) {
43681           c2 = str.charCodeAt(i + 1);
43682           arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
43683           i += 2;
43684         } else {
43685           c2 = str.charCodeAt(i + 1);
43686           c3 = str.charCodeAt(i + 2);
43687           arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
43688           i += 3;
43689         }
43690       }
43691     }
43692     return arr.join('');
43693   }
43694
43695   /**
43696    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
43697    * to work around bugs in some JS interpreters.
43698    */
43699
43700   function safe_add(x, y) {
43701     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
43702       msw = (x >> 16) + (y >> 16) + (lsw >> 16);
43703     return (msw << 16) | (lsw & 0xFFFF);
43704   }
43705
43706   /**
43707    * Bitwise rotate a 32-bit number to the left.
43708    */
43709
43710   function bit_rol(num, cnt) {
43711     return (num << cnt) | (num >>> (32 - cnt));
43712   }
43713
43714   /**
43715    * Convert a raw string to a hex string
43716    */
43717
43718   function rstr2hex(input, hexcase) {
43719     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
43720       output = '',
43721       x, i = 0,
43722       l = input.length;
43723     for (; i < l; i += 1) {
43724       x = input.charCodeAt(i);
43725       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
43726     }
43727     return output;
43728   }
43729
43730   /**
43731    * Encode a string as utf-16
43732    */
43733
43734   function str2rstr_utf16le(input) {
43735     var i, l = input.length,
43736       output = '';
43737     for (i = 0; i < l; i += 1) {
43738       output += String.fromCharCode(input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF);
43739     }
43740     return output;
43741   }
43742
43743   function str2rstr_utf16be(input) {
43744     var i, l = input.length,
43745       output = '';
43746     for (i = 0; i < l; i += 1) {
43747       output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF);
43748     }
43749     return output;
43750   }
43751
43752   /**
43753    * Convert an array of big-endian words to a string
43754    */
43755
43756   function binb2rstr(input) {
43757     var i, l = input.length * 32,
43758       output = '';
43759     for (i = 0; i < l; i += 8) {
43760       output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
43761     }
43762     return output;
43763   }
43764
43765   /**
43766    * Convert an array of little-endian words to a string
43767    */
43768
43769   function binl2rstr(input) {
43770     var i, l = input.length * 32,
43771       output = '';
43772     for (i = 0; i < l; i += 8) {
43773       output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
43774     }
43775     return output;
43776   }
43777
43778   /**
43779    * Convert a raw string to an array of little-endian words
43780    * Characters >255 have their high-byte silently ignored.
43781    */
43782
43783   function rstr2binl(input) {
43784     var i, l = input.length * 8,
43785       output = Array(input.length >> 2),
43786       lo = output.length;
43787     for (i = 0; i < lo; i += 1) {
43788       output[i] = 0;
43789     }
43790     for (i = 0; i < l; i += 8) {
43791       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
43792     }
43793     return output;
43794   }
43795
43796   /**
43797    * Convert a raw string to an array of big-endian words
43798    * Characters >255 have their high-byte silently ignored.
43799    */
43800
43801   function rstr2binb(input) {
43802     var i, l = input.length * 8,
43803       output = Array(input.length >> 2),
43804       lo = output.length;
43805     for (i = 0; i < lo; i += 1) {
43806       output[i] = 0;
43807     }
43808     for (i = 0; i < l; i += 8) {
43809       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
43810     }
43811     return output;
43812   }
43813
43814   /**
43815    * Convert a raw string to an arbitrary string encoding
43816    */
43817
43818   function rstr2any(input, encoding) {
43819     var divisor = encoding.length,
43820       remainders = Array(),
43821       i, q, x, ld, quotient, dividend, output, full_length;
43822
43823     /* Convert to an array of 16-bit big-endian values, forming the dividend */
43824     dividend = Array(Math.ceil(input.length / 2));
43825     ld = dividend.length;
43826     for (i = 0; i < ld; i += 1) {
43827       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
43828     }
43829
43830     /**
43831      * Repeatedly perform a long division. The binary array forms the dividend,
43832      * the length of the encoding is the divisor. Once computed, the quotient
43833      * forms the dividend for the next step. We stop when the dividend is zerHashes.
43834      * All remainders are stored for later use.
43835      */
43836     while (dividend.length > 0) {
43837       quotient = Array();
43838       x = 0;
43839       for (i = 0; i < dividend.length; i += 1) {
43840         x = (x << 16) + dividend[i];
43841         q = Math.floor(x / divisor);
43842         x -= q * divisor;
43843         if (quotient.length > 0 || q > 0) {
43844           quotient[quotient.length] = q;
43845         }
43846       }
43847       remainders[remainders.length] = x;
43848       dividend = quotient;
43849     }
43850
43851     /* Convert the remainders to the output string */
43852     output = '';
43853     for (i = remainders.length - 1; i >= 0; i--) {
43854       output += encoding.charAt(remainders[i]);
43855     }
43856
43857     /* Append leading zero equivalents */
43858     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
43859     for (i = output.length; i < full_length; i += 1) {
43860       output = encoding[0] + output;
43861     }
43862     return output;
43863   }
43864
43865   /**
43866    * Convert a raw string to a base-64 string
43867    */
43868
43869   function rstr2b64(input, b64pad) {
43870     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
43871       output = '',
43872       len = input.length,
43873       i, j, triplet;
43874     b64pad = b64pad || '=';
43875     for (i = 0; i < len; i += 3) {
43876       triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
43877       for (j = 0; j < 4; j += 1) {
43878         if (i * 8 + j * 6 > input.length * 8) {
43879           output += b64pad;
43880         } else {
43881           output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
43882         }
43883       }
43884     }
43885     return output;
43886   }
43887
43888   Hashes = {
43889     /**
43890      * @property {String} version
43891      * @readonly
43892      */
43893     VERSION: '1.0.5',
43894     /**
43895      * @member Hashes
43896      * @class Base64
43897      * @constructor
43898      */
43899     Base64: function() {
43900       // private properties
43901       var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
43902         pad = '=', // default pad according with the RFC standard
43903         url = false, // URL encoding support @todo
43904         utf8 = true; // by default enable UTF-8 support encoding
43905
43906       // public method for encoding
43907       this.encode = function(input) {
43908         var i, j, triplet,
43909           output = '',
43910           len = input.length;
43911
43912         pad = pad || '=';
43913         input = (utf8) ? utf8Encode(input) : input;
43914
43915         for (i = 0; i < len; i += 3) {
43916           triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
43917           for (j = 0; j < 4; j += 1) {
43918             if (i * 8 + j * 6 > len * 8) {
43919               output += pad;
43920             } else {
43921               output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
43922             }
43923           }
43924         }
43925         return output;
43926       };
43927
43928       // public method for decoding
43929       this.decode = function(input) {
43930         // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
43931         var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
43932           dec = '',
43933           arr = [];
43934         if (!input) {
43935           return input;
43936         }
43937
43938         i = ac = 0;
43939         input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
43940         //input += '';
43941
43942         do { // unpack four hexets into three octets using index points in b64
43943           h1 = tab.indexOf(input.charAt(i += 1));
43944           h2 = tab.indexOf(input.charAt(i += 1));
43945           h3 = tab.indexOf(input.charAt(i += 1));
43946           h4 = tab.indexOf(input.charAt(i += 1));
43947
43948           bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
43949
43950           o1 = bits >> 16 & 0xff;
43951           o2 = bits >> 8 & 0xff;
43952           o3 = bits & 0xff;
43953           ac += 1;
43954
43955           if (h3 === 64) {
43956             arr[ac] = String.fromCharCode(o1);
43957           } else if (h4 === 64) {
43958             arr[ac] = String.fromCharCode(o1, o2);
43959           } else {
43960             arr[ac] = String.fromCharCode(o1, o2, o3);
43961           }
43962         } while (i < input.length);
43963
43964         dec = arr.join('');
43965         dec = (utf8) ? utf8Decode(dec) : dec;
43966
43967         return dec;
43968       };
43969
43970       // set custom pad string
43971       this.setPad = function(str) {
43972         pad = str || pad;
43973         return this;
43974       };
43975       // set custom tab string characters
43976       this.setTab = function(str) {
43977         tab = str || tab;
43978         return this;
43979       };
43980       this.setUTF8 = function(bool) {
43981         if (typeof bool === 'boolean') {
43982           utf8 = bool;
43983         }
43984         return this;
43985       };
43986     },
43987
43988     /**
43989      * CRC-32 calculation
43990      * @member Hashes
43991      * @method CRC32
43992      * @static
43993      * @param {String} str Input String
43994      * @return {String}
43995      */
43996     CRC32: function(str) {
43997       var crc = 0,
43998         x = 0,
43999         y = 0,
44000         table, i, iTop;
44001       str = utf8Encode(str);
44002
44003       table = [
44004         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
44005         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
44006         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
44007         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
44008         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
44009         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
44010         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
44011         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
44012         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
44013         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
44014         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
44015         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
44016         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
44017         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
44018         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
44019         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
44020         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
44021         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
44022         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
44023         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
44024         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
44025         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
44026         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44027         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44028         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44029         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44030       ].join('');
44031
44032       crc = crc ^ (-1);
44033       for (i = 0, iTop = str.length; i < iTop; i += 1) {
44034         y = (crc ^ str.charCodeAt(i)) & 0xFF;
44035         x = '0x' + table.substr(y * 9, 8);
44036         crc = (crc >>> 8) ^ x;
44037       }
44038       // always return a positive number (that's what >>> 0 does)
44039       return (crc ^ (-1)) >>> 0;
44040     },
44041     /**
44042      * @member Hashes
44043      * @class MD5
44044      * @constructor
44045      * @param {Object} [config]
44046      *
44047      * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44048      * Digest Algorithm, as defined in RFC 1321.
44049      * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44050      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44051      * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44052      */
44053     MD5: function(options) {
44054       /**
44055        * Private config properties. You may need to tweak these to be compatible with
44056        * the server-side, but the defaults work in most cases.
44057        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44058        */
44059       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44060         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44061         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44062
44063       // privileged (public) methods
44064       this.hex = function(s) {
44065         return rstr2hex(rstr(s, utf8), hexcase);
44066       };
44067       this.b64 = function(s) {
44068         return rstr2b64(rstr(s), b64pad);
44069       };
44070       this.any = function(s, e) {
44071         return rstr2any(rstr(s, utf8), e);
44072       };
44073       this.raw = function(s) {
44074         return rstr(s, utf8);
44075       };
44076       this.hex_hmac = function(k, d) {
44077         return rstr2hex(rstr_hmac(k, d), hexcase);
44078       };
44079       this.b64_hmac = function(k, d) {
44080         return rstr2b64(rstr_hmac(k, d), b64pad);
44081       };
44082       this.any_hmac = function(k, d, e) {
44083         return rstr2any(rstr_hmac(k, d), e);
44084       };
44085       /**
44086        * Perform a simple self-test to see if the VM is working
44087        * @return {String} Hexadecimal hash sample
44088        */
44089       this.vm_test = function() {
44090         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44091       };
44092       /**
44093        * Enable/disable uppercase hexadecimal returned string
44094        * @param {Boolean}
44095        * @return {Object} this
44096        */
44097       this.setUpperCase = function(a) {
44098         if (typeof a === 'boolean') {
44099           hexcase = a;
44100         }
44101         return this;
44102       };
44103       /**
44104        * Defines a base64 pad string
44105        * @param {String} Pad
44106        * @return {Object} this
44107        */
44108       this.setPad = function(a) {
44109         b64pad = a || b64pad;
44110         return this;
44111       };
44112       /**
44113        * Defines a base64 pad string
44114        * @param {Boolean}
44115        * @return {Object} [this]
44116        */
44117       this.setUTF8 = function(a) {
44118         if (typeof a === 'boolean') {
44119           utf8 = a;
44120         }
44121         return this;
44122       };
44123
44124       // private methods
44125
44126       /**
44127        * Calculate the MD5 of a raw string
44128        */
44129
44130       function rstr(s) {
44131         s = (utf8) ? utf8Encode(s) : s;
44132         return binl2rstr(binl(rstr2binl(s), s.length * 8));
44133       }
44134
44135       /**
44136        * Calculate the HMAC-MD5, of a key and some data (raw strings)
44137        */
44138
44139       function rstr_hmac(key, data) {
44140         var bkey, ipad, opad, hash, i;
44141
44142         key = (utf8) ? utf8Encode(key) : key;
44143         data = (utf8) ? utf8Encode(data) : data;
44144         bkey = rstr2binl(key);
44145         if (bkey.length > 16) {
44146           bkey = binl(bkey, key.length * 8);
44147         }
44148
44149         ipad = Array(16), opad = Array(16);
44150         for (i = 0; i < 16; i += 1) {
44151           ipad[i] = bkey[i] ^ 0x36363636;
44152           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44153         }
44154         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44155         return binl2rstr(binl(opad.concat(hash), 512 + 128));
44156       }
44157
44158       /**
44159        * Calculate the MD5 of an array of little-endian words, and a bit length.
44160        */
44161
44162       function binl(x, len) {
44163         var i, olda, oldb, oldc, oldd,
44164           a = 1732584193,
44165           b = -271733879,
44166           c = -1732584194,
44167           d = 271733878;
44168
44169         /* append padding */
44170         x[len >> 5] |= 0x80 << ((len) % 32);
44171         x[(((len + 64) >>> 9) << 4) + 14] = len;
44172
44173         for (i = 0; i < x.length; i += 16) {
44174           olda = a;
44175           oldb = b;
44176           oldc = c;
44177           oldd = d;
44178
44179           a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44180           d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44181           c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44182           b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44183           a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44184           d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44185           c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44186           b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44187           a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44188           d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44189           c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44190           b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44191           a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44192           d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44193           c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44194           b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44195
44196           a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44197           d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44198           c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44199           b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44200           a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44201           d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44202           c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44203           b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44204           a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44205           d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44206           c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44207           b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44208           a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44209           d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44210           c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44211           b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44212
44213           a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44214           d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44215           c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44216           b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44217           a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44218           d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44219           c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44220           b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44221           a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44222           d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44223           c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44224           b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44225           a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44226           d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44227           c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44228           b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
44229
44230           a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
44231           d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
44232           c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
44233           b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
44234           a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
44235           d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
44236           c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
44237           b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
44238           a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
44239           d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
44240           c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
44241           b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
44242           a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
44243           d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
44244           c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
44245           b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
44246
44247           a = safe_add(a, olda);
44248           b = safe_add(b, oldb);
44249           c = safe_add(c, oldc);
44250           d = safe_add(d, oldd);
44251         }
44252         return Array(a, b, c, d);
44253       }
44254
44255       /**
44256        * These functions implement the four basic operations the algorithm uses.
44257        */
44258
44259       function md5_cmn(q, a, b, x, s, t) {
44260         return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
44261       }
44262
44263       function md5_ff(a, b, c, d, x, s, t) {
44264         return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44265       }
44266
44267       function md5_gg(a, b, c, d, x, s, t) {
44268         return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44269       }
44270
44271       function md5_hh(a, b, c, d, x, s, t) {
44272         return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44273       }
44274
44275       function md5_ii(a, b, c, d, x, s, t) {
44276         return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44277       }
44278     },
44279     /**
44280      * @member Hashes
44281      * @class Hashes.SHA1
44282      * @param {Object} [config]
44283      * @constructor
44284      *
44285      * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
44286      * Version 2.2 Copyright Paul Johnston 2000 - 2009.
44287      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44288      * See http://pajhome.org.uk/crypt/md5 for details.
44289      */
44290     SHA1: function(options) {
44291       /**
44292        * Private config properties. You may need to tweak these to be compatible with
44293        * the server-side, but the defaults work in most cases.
44294        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44295        */
44296       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44297         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44298         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44299
44300       // public methods
44301       this.hex = function(s) {
44302         return rstr2hex(rstr(s, utf8), hexcase);
44303       };
44304       this.b64 = function(s) {
44305         return rstr2b64(rstr(s, utf8), b64pad);
44306       };
44307       this.any = function(s, e) {
44308         return rstr2any(rstr(s, utf8), e);
44309       };
44310       this.raw = function(s) {
44311         return rstr(s, utf8);
44312       };
44313       this.hex_hmac = function(k, d) {
44314         return rstr2hex(rstr_hmac(k, d));
44315       };
44316       this.b64_hmac = function(k, d) {
44317         return rstr2b64(rstr_hmac(k, d), b64pad);
44318       };
44319       this.any_hmac = function(k, d, e) {
44320         return rstr2any(rstr_hmac(k, d), e);
44321       };
44322       /**
44323        * Perform a simple self-test to see if the VM is working
44324        * @return {String} Hexadecimal hash sample
44325        * @public
44326        */
44327       this.vm_test = function() {
44328         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44329       };
44330       /**
44331        * @description Enable/disable uppercase hexadecimal returned string
44332        * @param {boolean}
44333        * @return {Object} this
44334        * @public
44335        */
44336       this.setUpperCase = function(a) {
44337         if (typeof a === 'boolean') {
44338           hexcase = a;
44339         }
44340         return this;
44341       };
44342       /**
44343        * @description Defines a base64 pad string
44344        * @param {string} Pad
44345        * @return {Object} this
44346        * @public
44347        */
44348       this.setPad = function(a) {
44349         b64pad = a || b64pad;
44350         return this;
44351       };
44352       /**
44353        * @description Defines a base64 pad string
44354        * @param {boolean}
44355        * @return {Object} this
44356        * @public
44357        */
44358       this.setUTF8 = function(a) {
44359         if (typeof a === 'boolean') {
44360           utf8 = a;
44361         }
44362         return this;
44363       };
44364
44365       // private methods
44366
44367       /**
44368        * Calculate the SHA-512 of a raw string
44369        */
44370
44371       function rstr(s) {
44372         s = (utf8) ? utf8Encode(s) : s;
44373         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44374       }
44375
44376       /**
44377        * Calculate the HMAC-SHA1 of a key and some data (raw strings)
44378        */
44379
44380       function rstr_hmac(key, data) {
44381         var bkey, ipad, opad, i, hash;
44382         key = (utf8) ? utf8Encode(key) : key;
44383         data = (utf8) ? utf8Encode(data) : data;
44384         bkey = rstr2binb(key);
44385
44386         if (bkey.length > 16) {
44387           bkey = binb(bkey, key.length * 8);
44388         }
44389         ipad = Array(16), opad = Array(16);
44390         for (i = 0; i < 16; i += 1) {
44391           ipad[i] = bkey[i] ^ 0x36363636;
44392           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44393         }
44394         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44395         return binb2rstr(binb(opad.concat(hash), 512 + 160));
44396       }
44397
44398       /**
44399        * Calculate the SHA-1 of an array of big-endian words, and a bit length
44400        */
44401
44402       function binb(x, len) {
44403         var i, j, t, olda, oldb, oldc, oldd, olde,
44404           w = Array(80),
44405           a = 1732584193,
44406           b = -271733879,
44407           c = -1732584194,
44408           d = 271733878,
44409           e = -1009589776;
44410
44411         /* append padding */
44412         x[len >> 5] |= 0x80 << (24 - len % 32);
44413         x[((len + 64 >> 9) << 4) + 15] = len;
44414
44415         for (i = 0; i < x.length; i += 16) {
44416           olda = a,
44417           oldb = b;
44418           oldc = c;
44419           oldd = d;
44420           olde = e;
44421
44422           for (j = 0; j < 80; j += 1) {
44423             if (j < 16) {
44424               w[j] = x[i + j];
44425             } else {
44426               w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
44427             }
44428             t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
44429               safe_add(safe_add(e, w[j]), sha1_kt(j)));
44430             e = d;
44431             d = c;
44432             c = bit_rol(b, 30);
44433             b = a;
44434             a = t;
44435           }
44436
44437           a = safe_add(a, olda);
44438           b = safe_add(b, oldb);
44439           c = safe_add(c, oldc);
44440           d = safe_add(d, oldd);
44441           e = safe_add(e, olde);
44442         }
44443         return Array(a, b, c, d, e);
44444       }
44445
44446       /**
44447        * Perform the appropriate triplet combination function for the current
44448        * iteration
44449        */
44450
44451       function sha1_ft(t, b, c, d) {
44452         if (t < 20) {
44453           return (b & c) | ((~b) & d);
44454         }
44455         if (t < 40) {
44456           return b ^ c ^ d;
44457         }
44458         if (t < 60) {
44459           return (b & c) | (b & d) | (c & d);
44460         }
44461         return b ^ c ^ d;
44462       }
44463
44464       /**
44465        * Determine the appropriate additive constant for the current iteration
44466        */
44467
44468       function sha1_kt(t) {
44469         return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
44470           (t < 60) ? -1894007588 : -899497514;
44471       }
44472     },
44473     /**
44474      * @class Hashes.SHA256
44475      * @param {config}
44476      *
44477      * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
44478      * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
44479      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44480      * See http://pajhome.org.uk/crypt/md5 for details.
44481      * Also http://anmar.eu.org/projects/jssha2/
44482      */
44483     SHA256: function(options) {
44484       /**
44485        * Private properties configuration variables. You may need to tweak these to be compatible with
44486        * the server-side, but the defaults work in most cases.
44487        * @see this.setUpperCase() method
44488        * @see this.setPad() method
44489        */
44490       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
44491         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
44492         /* base-64 pad character. Default '=' for strict RFC compliance   */
44493         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
44494         /* enable/disable utf8 encoding */
44495         sha256_K;
44496
44497       /* privileged (public) methods */
44498       this.hex = function(s) {
44499         return rstr2hex(rstr(s, utf8));
44500       };
44501       this.b64 = function(s) {
44502         return rstr2b64(rstr(s, utf8), b64pad);
44503       };
44504       this.any = function(s, e) {
44505         return rstr2any(rstr(s, utf8), e);
44506       };
44507       this.raw = function(s) {
44508         return rstr(s, utf8);
44509       };
44510       this.hex_hmac = function(k, d) {
44511         return rstr2hex(rstr_hmac(k, d));
44512       };
44513       this.b64_hmac = function(k, d) {
44514         return rstr2b64(rstr_hmac(k, d), b64pad);
44515       };
44516       this.any_hmac = function(k, d, e) {
44517         return rstr2any(rstr_hmac(k, d), e);
44518       };
44519       /**
44520        * Perform a simple self-test to see if the VM is working
44521        * @return {String} Hexadecimal hash sample
44522        * @public
44523        */
44524       this.vm_test = function() {
44525         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44526       };
44527       /**
44528        * Enable/disable uppercase hexadecimal returned string
44529        * @param {boolean}
44530        * @return {Object} this
44531        * @public
44532        */
44533       this.setUpperCase = function(a) {
44534         if (typeof a === 'boolean') {
44535           hexcase = a;
44536         }
44537         return this;
44538       };
44539       /**
44540        * @description Defines a base64 pad string
44541        * @param {string} Pad
44542        * @return {Object} this
44543        * @public
44544        */
44545       this.setPad = function(a) {
44546         b64pad = a || b64pad;
44547         return this;
44548       };
44549       /**
44550        * Defines a base64 pad string
44551        * @param {boolean}
44552        * @return {Object} this
44553        * @public
44554        */
44555       this.setUTF8 = function(a) {
44556         if (typeof a === 'boolean') {
44557           utf8 = a;
44558         }
44559         return this;
44560       };
44561
44562       // private methods
44563
44564       /**
44565        * Calculate the SHA-512 of a raw string
44566        */
44567
44568       function rstr(s, utf8) {
44569         s = (utf8) ? utf8Encode(s) : s;
44570         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44571       }
44572
44573       /**
44574        * Calculate the HMAC-sha256 of a key and some data (raw strings)
44575        */
44576
44577       function rstr_hmac(key, data) {
44578         key = (utf8) ? utf8Encode(key) : key;
44579         data = (utf8) ? utf8Encode(data) : data;
44580         var hash, i = 0,
44581           bkey = rstr2binb(key),
44582           ipad = Array(16),
44583           opad = Array(16);
44584
44585         if (bkey.length > 16) {
44586           bkey = binb(bkey, key.length * 8);
44587         }
44588
44589         for (; i < 16; i += 1) {
44590           ipad[i] = bkey[i] ^ 0x36363636;
44591           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44592         }
44593
44594         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44595         return binb2rstr(binb(opad.concat(hash), 512 + 256));
44596       }
44597
44598       /*
44599        * Main sha256 function, with its support functions
44600        */
44601
44602       function sha256_S(X, n) {
44603         return (X >>> n) | (X << (32 - n));
44604       }
44605
44606       function sha256_R(X, n) {
44607         return (X >>> n);
44608       }
44609
44610       function sha256_Ch(x, y, z) {
44611         return ((x & y) ^ ((~x) & z));
44612       }
44613
44614       function sha256_Maj(x, y, z) {
44615         return ((x & y) ^ (x & z) ^ (y & z));
44616       }
44617
44618       function sha256_Sigma0256(x) {
44619         return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
44620       }
44621
44622       function sha256_Sigma1256(x) {
44623         return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
44624       }
44625
44626       function sha256_Gamma0256(x) {
44627         return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
44628       }
44629
44630       function sha256_Gamma1256(x) {
44631         return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
44632       }
44633
44634       function sha256_Sigma0512(x) {
44635         return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));
44636       }
44637
44638       function sha256_Sigma1512(x) {
44639         return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));
44640       }
44641
44642       function sha256_Gamma0512(x) {
44643         return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));
44644       }
44645
44646       function sha256_Gamma1512(x) {
44647         return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));
44648       }
44649
44650       sha256_K = [
44651         1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
44652         1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
44653         264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
44654         113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
44655         1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
44656         430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
44657         1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
44658       ];
44659
44660       function binb(m, l) {
44661         var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
44662           1359893119, -1694144372, 528734635, 1541459225
44663         ];
44664         var W = new Array(64);
44665         var a, b, c, d, e, f, g, h;
44666         var i, j, T1, T2;
44667
44668         /* append padding */
44669         m[l >> 5] |= 0x80 << (24 - l % 32);
44670         m[((l + 64 >> 9) << 4) + 15] = l;
44671
44672         for (i = 0; i < m.length; i += 16) {
44673           a = HASH[0];
44674           b = HASH[1];
44675           c = HASH[2];
44676           d = HASH[3];
44677           e = HASH[4];
44678           f = HASH[5];
44679           g = HASH[6];
44680           h = HASH[7];
44681
44682           for (j = 0; j < 64; j += 1) {
44683             if (j < 16) {
44684               W[j] = m[j + i];
44685             } else {
44686               W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
44687                 sha256_Gamma0256(W[j - 15])), W[j - 16]);
44688             }
44689
44690             T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
44691               sha256_K[j]), W[j]);
44692             T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
44693             h = g;
44694             g = f;
44695             f = e;
44696             e = safe_add(d, T1);
44697             d = c;
44698             c = b;
44699             b = a;
44700             a = safe_add(T1, T2);
44701           }
44702
44703           HASH[0] = safe_add(a, HASH[0]);
44704           HASH[1] = safe_add(b, HASH[1]);
44705           HASH[2] = safe_add(c, HASH[2]);
44706           HASH[3] = safe_add(d, HASH[3]);
44707           HASH[4] = safe_add(e, HASH[4]);
44708           HASH[5] = safe_add(f, HASH[5]);
44709           HASH[6] = safe_add(g, HASH[6]);
44710           HASH[7] = safe_add(h, HASH[7]);
44711         }
44712         return HASH;
44713       }
44714
44715     },
44716
44717     /**
44718      * @class Hashes.SHA512
44719      * @param {config}
44720      *
44721      * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
44722      * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
44723      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44724      * See http://pajhome.org.uk/crypt/md5 for details.
44725      */
44726     SHA512: function(options) {
44727       /**
44728        * Private properties configuration variables. You may need to tweak these to be compatible with
44729        * the server-side, but the defaults work in most cases.
44730        * @see this.setUpperCase() method
44731        * @see this.setPad() method
44732        */
44733       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
44734         /* hexadecimal output case format. false - lowercase; true - uppercase  */
44735         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
44736         /* base-64 pad character. Default '=' for strict RFC compliance   */
44737         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
44738         /* enable/disable utf8 encoding */
44739         sha512_k;
44740
44741       /* privileged (public) methods */
44742       this.hex = function(s) {
44743         return rstr2hex(rstr(s));
44744       };
44745       this.b64 = function(s) {
44746         return rstr2b64(rstr(s), b64pad);
44747       };
44748       this.any = function(s, e) {
44749         return rstr2any(rstr(s), e);
44750       };
44751       this.raw = function(s) {
44752         return rstr(s, utf8);
44753       };
44754       this.hex_hmac = function(k, d) {
44755         return rstr2hex(rstr_hmac(k, d));
44756       };
44757       this.b64_hmac = function(k, d) {
44758         return rstr2b64(rstr_hmac(k, d), b64pad);
44759       };
44760       this.any_hmac = function(k, d, e) {
44761         return rstr2any(rstr_hmac(k, d), e);
44762       };
44763       /**
44764        * Perform a simple self-test to see if the VM is working
44765        * @return {String} Hexadecimal hash sample
44766        * @public
44767        */
44768       this.vm_test = function() {
44769         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44770       };
44771       /**
44772        * @description Enable/disable uppercase hexadecimal returned string
44773        * @param {boolean}
44774        * @return {Object} this
44775        * @public
44776        */
44777       this.setUpperCase = function(a) {
44778         if (typeof a === 'boolean') {
44779           hexcase = a;
44780         }
44781         return this;
44782       };
44783       /**
44784        * @description Defines a base64 pad string
44785        * @param {string} Pad
44786        * @return {Object} this
44787        * @public
44788        */
44789       this.setPad = function(a) {
44790         b64pad = a || b64pad;
44791         return this;
44792       };
44793       /**
44794        * @description Defines a base64 pad string
44795        * @param {boolean}
44796        * @return {Object} this
44797        * @public
44798        */
44799       this.setUTF8 = function(a) {
44800         if (typeof a === 'boolean') {
44801           utf8 = a;
44802         }
44803         return this;
44804       };
44805
44806       /* private methods */
44807
44808       /**
44809        * Calculate the SHA-512 of a raw string
44810        */
44811
44812       function rstr(s) {
44813         s = (utf8) ? utf8Encode(s) : s;
44814         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44815       }
44816       /*
44817        * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
44818        */
44819
44820       function rstr_hmac(key, data) {
44821         key = (utf8) ? utf8Encode(key) : key;
44822         data = (utf8) ? utf8Encode(data) : data;
44823
44824         var hash, i = 0,
44825           bkey = rstr2binb(key),
44826           ipad = Array(32),
44827           opad = Array(32);
44828
44829         if (bkey.length > 32) {
44830           bkey = binb(bkey, key.length * 8);
44831         }
44832
44833         for (; i < 32; i += 1) {
44834           ipad[i] = bkey[i] ^ 0x36363636;
44835           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44836         }
44837
44838         hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
44839         return binb2rstr(binb(opad.concat(hash), 1024 + 512));
44840       }
44841
44842       /**
44843        * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
44844        */
44845
44846       function binb(x, len) {
44847         var j, i, l,
44848           W = new Array(80),
44849           hash = new Array(16),
44850           //Initial hash values
44851           H = [
44852             new int64(0x6a09e667, -205731576),
44853             new int64(-1150833019, -2067093701),
44854             new int64(0x3c6ef372, -23791573),
44855             new int64(-1521486534, 0x5f1d36f1),
44856             new int64(0x510e527f, -1377402159),
44857             new int64(-1694144372, 0x2b3e6c1f),
44858             new int64(0x1f83d9ab, -79577749),
44859             new int64(0x5be0cd19, 0x137e2179)
44860           ],
44861           T1 = new int64(0, 0),
44862           T2 = new int64(0, 0),
44863           a = new int64(0, 0),
44864           b = new int64(0, 0),
44865           c = new int64(0, 0),
44866           d = new int64(0, 0),
44867           e = new int64(0, 0),
44868           f = new int64(0, 0),
44869           g = new int64(0, 0),
44870           h = new int64(0, 0),
44871           //Temporary variables not specified by the document
44872           s0 = new int64(0, 0),
44873           s1 = new int64(0, 0),
44874           Ch = new int64(0, 0),
44875           Maj = new int64(0, 0),
44876           r1 = new int64(0, 0),
44877           r2 = new int64(0, 0),
44878           r3 = new int64(0, 0);
44879
44880         if (sha512_k === undefined) {
44881           //SHA512 constants
44882           sha512_k = [
44883             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
44884             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
44885             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
44886             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
44887             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
44888             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
44889             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
44890             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
44891             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
44892             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
44893             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
44894             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
44895             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
44896             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
44897             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
44898             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
44899             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
44900             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
44901             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
44902             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
44903             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
44904             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
44905             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
44906             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
44907             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
44908             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
44909             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
44910             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
44911             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
44912             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
44913             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
44914             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
44915             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
44916             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
44917             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
44918             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
44919             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
44920             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
44921             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
44922             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
44923           ];
44924         }
44925
44926         for (i = 0; i < 80; i += 1) {
44927           W[i] = new int64(0, 0);
44928         }
44929
44930         // append padding to the source string. The format is described in the FIPS.
44931         x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
44932         x[((len + 128 >> 10) << 5) + 31] = len;
44933         l = x.length;
44934         for (i = 0; i < l; i += 32) { //32 dwords is the block size
44935           int64copy(a, H[0]);
44936           int64copy(b, H[1]);
44937           int64copy(c, H[2]);
44938           int64copy(d, H[3]);
44939           int64copy(e, H[4]);
44940           int64copy(f, H[5]);
44941           int64copy(g, H[6]);
44942           int64copy(h, H[7]);
44943
44944           for (j = 0; j < 16; j += 1) {
44945             W[j].h = x[i + 2 * j];
44946             W[j].l = x[i + 2 * j + 1];
44947           }
44948
44949           for (j = 16; j < 80; j += 1) {
44950             //sigma1
44951             int64rrot(r1, W[j - 2], 19);
44952             int64revrrot(r2, W[j - 2], 29);
44953             int64shr(r3, W[j - 2], 6);
44954             s1.l = r1.l ^ r2.l ^ r3.l;
44955             s1.h = r1.h ^ r2.h ^ r3.h;
44956             //sigma0
44957             int64rrot(r1, W[j - 15], 1);
44958             int64rrot(r2, W[j - 15], 8);
44959             int64shr(r3, W[j - 15], 7);
44960             s0.l = r1.l ^ r2.l ^ r3.l;
44961             s0.h = r1.h ^ r2.h ^ r3.h;
44962
44963             int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
44964           }
44965
44966           for (j = 0; j < 80; j += 1) {
44967             //Ch
44968             Ch.l = (e.l & f.l) ^ (~e.l & g.l);
44969             Ch.h = (e.h & f.h) ^ (~e.h & g.h);
44970
44971             //Sigma1
44972             int64rrot(r1, e, 14);
44973             int64rrot(r2, e, 18);
44974             int64revrrot(r3, e, 9);
44975             s1.l = r1.l ^ r2.l ^ r3.l;
44976             s1.h = r1.h ^ r2.h ^ r3.h;
44977
44978             //Sigma0
44979             int64rrot(r1, a, 28);
44980             int64revrrot(r2, a, 2);
44981             int64revrrot(r3, a, 7);
44982             s0.l = r1.l ^ r2.l ^ r3.l;
44983             s0.h = r1.h ^ r2.h ^ r3.h;
44984
44985             //Maj
44986             Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
44987             Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
44988
44989             int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
44990             int64add(T2, s0, Maj);
44991
44992             int64copy(h, g);
44993             int64copy(g, f);
44994             int64copy(f, e);
44995             int64add(e, d, T1);
44996             int64copy(d, c);
44997             int64copy(c, b);
44998             int64copy(b, a);
44999             int64add(a, T1, T2);
45000           }
45001           int64add(H[0], H[0], a);
45002           int64add(H[1], H[1], b);
45003           int64add(H[2], H[2], c);
45004           int64add(H[3], H[3], d);
45005           int64add(H[4], H[4], e);
45006           int64add(H[5], H[5], f);
45007           int64add(H[6], H[6], g);
45008           int64add(H[7], H[7], h);
45009         }
45010
45011         //represent the hash as an array of 32-bit dwords
45012         for (i = 0; i < 8; i += 1) {
45013           hash[2 * i] = H[i].h;
45014           hash[2 * i + 1] = H[i].l;
45015         }
45016         return hash;
45017       }
45018
45019       //A constructor for 64-bit numbers
45020
45021       function int64(h, l) {
45022         this.h = h;
45023         this.l = l;
45024         //this.toString = int64toString;
45025       }
45026
45027       //Copies src into dst, assuming both are 64-bit numbers
45028
45029       function int64copy(dst, src) {
45030         dst.h = src.h;
45031         dst.l = src.l;
45032       }
45033
45034       //Right-rotates a 64-bit number by shift
45035       //Won't handle cases of shift>=32
45036       //The function revrrot() is for that
45037
45038       function int64rrot(dst, x, shift) {
45039         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45040         dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45041       }
45042
45043       //Reverses the dwords of the source and then rotates right by shift.
45044       //This is equivalent to rotation by 32+shift
45045
45046       function int64revrrot(dst, x, shift) {
45047         dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45048         dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45049       }
45050
45051       //Bitwise-shifts right a 64-bit number by shift
45052       //Won't handle shift>=32, but it's never needed in SHA512
45053
45054       function int64shr(dst, x, shift) {
45055         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45056         dst.h = (x.h >>> shift);
45057       }
45058
45059       //Adds two 64-bit numbers
45060       //Like the original implementation, does not rely on 32-bit operations
45061
45062       function int64add(dst, x, y) {
45063         var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45064         var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45065         var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45066         var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45067         dst.l = (w0 & 0xffff) | (w1 << 16);
45068         dst.h = (w2 & 0xffff) | (w3 << 16);
45069       }
45070
45071       //Same, except with 4 addends. Works faster than adding them one by one.
45072
45073       function int64add4(dst, a, b, c, d) {
45074         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45075         var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45076         var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45077         var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45078         dst.l = (w0 & 0xffff) | (w1 << 16);
45079         dst.h = (w2 & 0xffff) | (w3 << 16);
45080       }
45081
45082       //Same, except with 5 addends
45083
45084       function int64add5(dst, a, b, c, d, e) {
45085         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45086           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45087           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45088           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45089         dst.l = (w0 & 0xffff) | (w1 << 16);
45090         dst.h = (w2 & 0xffff) | (w3 << 16);
45091       }
45092     },
45093     /**
45094      * @class Hashes.RMD160
45095      * @constructor
45096      * @param {Object} [config]
45097      *
45098      * A JavaScript implementation of the RIPEMD-160 Algorithm
45099      * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45100      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45101      * See http://pajhome.org.uk/crypt/md5 for details.
45102      * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45103      */
45104     RMD160: function(options) {
45105       /**
45106        * Private properties configuration variables. You may need to tweak these to be compatible with
45107        * the server-side, but the defaults work in most cases.
45108        * @see this.setUpperCase() method
45109        * @see this.setPad() method
45110        */
45111       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45112         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45113         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45114         /* base-64 pad character. Default '=' for strict RFC compliance   */
45115         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45116         /* enable/disable utf8 encoding */
45117         rmd160_r1 = [
45118           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45119           7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45120           3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45121           1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45122           4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45123         ],
45124         rmd160_r2 = [
45125           5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45126           6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45127           15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45128           8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45129           12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45130         ],
45131         rmd160_s1 = [
45132           11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45133           7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45134           11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45135           11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45136           9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45137         ],
45138         rmd160_s2 = [
45139           8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45140           9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45141           9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45142           15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45143           8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45144         ];
45145
45146       /* privileged (public) methods */
45147       this.hex = function(s) {
45148         return rstr2hex(rstr(s, utf8));
45149       };
45150       this.b64 = function(s) {
45151         return rstr2b64(rstr(s, utf8), b64pad);
45152       };
45153       this.any = function(s, e) {
45154         return rstr2any(rstr(s, utf8), e);
45155       };
45156       this.raw = function(s) {
45157         return rstr(s, utf8);
45158       };
45159       this.hex_hmac = function(k, d) {
45160         return rstr2hex(rstr_hmac(k, d));
45161       };
45162       this.b64_hmac = function(k, d) {
45163         return rstr2b64(rstr_hmac(k, d), b64pad);
45164       };
45165       this.any_hmac = function(k, d, e) {
45166         return rstr2any(rstr_hmac(k, d), e);
45167       };
45168       /**
45169        * Perform a simple self-test to see if the VM is working
45170        * @return {String} Hexadecimal hash sample
45171        * @public
45172        */
45173       this.vm_test = function() {
45174         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45175       };
45176       /**
45177        * @description Enable/disable uppercase hexadecimal returned string
45178        * @param {boolean}
45179        * @return {Object} this
45180        * @public
45181        */
45182       this.setUpperCase = function(a) {
45183         if (typeof a === 'boolean') {
45184           hexcase = a;
45185         }
45186         return this;
45187       };
45188       /**
45189        * @description Defines a base64 pad string
45190        * @param {string} Pad
45191        * @return {Object} this
45192        * @public
45193        */
45194       this.setPad = function(a) {
45195         if (typeof a !== 'undefined') {
45196           b64pad = a;
45197         }
45198         return this;
45199       };
45200       /**
45201        * @description Defines a base64 pad string
45202        * @param {boolean}
45203        * @return {Object} this
45204        * @public
45205        */
45206       this.setUTF8 = function(a) {
45207         if (typeof a === 'boolean') {
45208           utf8 = a;
45209         }
45210         return this;
45211       };
45212
45213       /* private methods */
45214
45215       /**
45216        * Calculate the rmd160 of a raw string
45217        */
45218
45219       function rstr(s) {
45220         s = (utf8) ? utf8Encode(s) : s;
45221         return binl2rstr(binl(rstr2binl(s), s.length * 8));
45222       }
45223
45224       /**
45225        * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45226        */
45227
45228       function rstr_hmac(key, data) {
45229         key = (utf8) ? utf8Encode(key) : key;
45230         data = (utf8) ? utf8Encode(data) : data;
45231         var i, hash,
45232           bkey = rstr2binl(key),
45233           ipad = Array(16),
45234           opad = Array(16);
45235
45236         if (bkey.length > 16) {
45237           bkey = binl(bkey, key.length * 8);
45238         }
45239
45240         for (i = 0; i < 16; i += 1) {
45241           ipad[i] = bkey[i] ^ 0x36363636;
45242           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45243         }
45244         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45245         return binl2rstr(binl(opad.concat(hash), 512 + 160));
45246       }
45247
45248       /**
45249        * Convert an array of little-endian words to a string
45250        */
45251
45252       function binl2rstr(input) {
45253         var i, output = '',
45254           l = input.length * 32;
45255         for (i = 0; i < l; i += 8) {
45256           output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
45257         }
45258         return output;
45259       }
45260
45261       /**
45262        * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
45263        */
45264
45265       function binl(x, len) {
45266         var T, j, i, l,
45267           h0 = 0x67452301,
45268           h1 = 0xefcdab89,
45269           h2 = 0x98badcfe,
45270           h3 = 0x10325476,
45271           h4 = 0xc3d2e1f0,
45272           A1, B1, C1, D1, E1,
45273           A2, B2, C2, D2, E2;
45274
45275         /* append padding */
45276         x[len >> 5] |= 0x80 << (len % 32);
45277         x[(((len + 64) >>> 9) << 4) + 14] = len;
45278         l = x.length;
45279
45280         for (i = 0; i < l; i += 16) {
45281           A1 = A2 = h0;
45282           B1 = B2 = h1;
45283           C1 = C2 = h2;
45284           D1 = D2 = h3;
45285           E1 = E2 = h4;
45286           for (j = 0; j <= 79; j += 1) {
45287             T = safe_add(A1, rmd160_f(j, B1, C1, D1));
45288             T = safe_add(T, x[i + rmd160_r1[j]]);
45289             T = safe_add(T, rmd160_K1(j));
45290             T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
45291             A1 = E1;
45292             E1 = D1;
45293             D1 = bit_rol(C1, 10);
45294             C1 = B1;
45295             B1 = T;
45296             T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
45297             T = safe_add(T, x[i + rmd160_r2[j]]);
45298             T = safe_add(T, rmd160_K2(j));
45299             T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
45300             A2 = E2;
45301             E2 = D2;
45302             D2 = bit_rol(C2, 10);
45303             C2 = B2;
45304             B2 = T;
45305           }
45306
45307           T = safe_add(h1, safe_add(C1, D2));
45308           h1 = safe_add(h2, safe_add(D1, E2));
45309           h2 = safe_add(h3, safe_add(E1, A2));
45310           h3 = safe_add(h4, safe_add(A1, B2));
45311           h4 = safe_add(h0, safe_add(B1, C2));
45312           h0 = T;
45313         }
45314         return [h0, h1, h2, h3, h4];
45315       }
45316
45317       // specific algorithm methods
45318
45319       function rmd160_f(j, x, y, z) {
45320         return (0 <= j && j <= 15) ? (x ^ y ^ z) :
45321           (16 <= j && j <= 31) ? (x & y) | (~x & z) :
45322           (32 <= j && j <= 47) ? (x | ~y) ^ z :
45323           (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
45324           (64 <= j && j <= 79) ? x ^ (y | ~z) :
45325           'rmd160_f: j out of range';
45326       }
45327
45328       function rmd160_K1(j) {
45329         return (0 <= j && j <= 15) ? 0x00000000 :
45330           (16 <= j && j <= 31) ? 0x5a827999 :
45331           (32 <= j && j <= 47) ? 0x6ed9eba1 :
45332           (48 <= j && j <= 63) ? 0x8f1bbcdc :
45333           (64 <= j && j <= 79) ? 0xa953fd4e :
45334           'rmd160_K1: j out of range';
45335       }
45336
45337       function rmd160_K2(j) {
45338         return (0 <= j && j <= 15) ? 0x50a28be6 :
45339           (16 <= j && j <= 31) ? 0x5c4dd124 :
45340           (32 <= j && j <= 47) ? 0x6d703ef3 :
45341           (48 <= j && j <= 63) ? 0x7a6d76e9 :
45342           (64 <= j && j <= 79) ? 0x00000000 :
45343           'rmd160_K2: j out of range';
45344       }
45345     }
45346   };
45347
45348   // exposes Hashes
45349   (function(window, undefined) {
45350     var freeExports = false;
45351     if (typeof exports === 'object') {
45352       freeExports = exports;
45353       if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
45354         window = commonjsGlobal;
45355       }
45356     }
45357
45358     if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
45359       // define as an anonymous module, so, through path mapping, it can be aliased
45360       define(function() {
45361         return Hashes;
45362       });
45363     } else if (freeExports) {
45364       // in Node.js or RingoJS v0.8.0+
45365       if (typeof module === 'object' && module && module.exports === freeExports) {
45366         module.exports = Hashes;
45367       }
45368       // in Narwhal or RingoJS v0.7.0-
45369       else {
45370         freeExports.Hashes = Hashes;
45371       }
45372     } else {
45373       // in a browser or Rhino
45374       window.Hashes = Hashes;
45375     }
45376   }(this));
45377 }()); // IIFE
45378 });
45379
45380 var immutable = extend$2;
45381
45382 var hasOwnProperty = Object.prototype.hasOwnProperty;
45383
45384 function extend$2() {
45385     var target = {};
45386
45387     for (var i = 0; i < arguments.length; i++) {
45388         var source = arguments[i];
45389
45390         for (var key in source) {
45391             if (hasOwnProperty.call(source, key)) {
45392                 target[key] = source[key];
45393             }
45394         }
45395     }
45396
45397     return target
45398 }
45399
45400 var hashes = hashes$1;
45401 var xtend$1 = immutable;
45402 var sha1 = new hashes.SHA1();
45403
45404 var ohauth$1 = {};
45405
45406 ohauth$1.qsString = function(obj) {
45407     return Object.keys(obj).sort().map(function(key) {
45408         return ohauth$1.percentEncode(key) + '=' +
45409             ohauth$1.percentEncode(obj[key]);
45410     }).join('&');
45411 };
45412
45413 ohauth$1.stringQs = function(str) {
45414     return str.split('&').filter(function (pair) {
45415         return pair !== '';
45416     }).reduce(function(obj, pair){
45417         var parts = pair.split('=');
45418         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
45419             '' : decodeURIComponent(parts[1]);
45420         return obj;
45421     }, {});
45422 };
45423
45424 ohauth$1.rawxhr = function(method, url, data, headers, callback) {
45425     var xhr = new XMLHttpRequest(),
45426         twoHundred = /^20\d$/;
45427     xhr.onreadystatechange = function() {
45428         if (4 === xhr.readyState && 0 !== xhr.status) {
45429             if (twoHundred.test(xhr.status)) callback(null, xhr);
45430             else return callback(xhr, null);
45431         }
45432     };
45433     xhr.onerror = function(e) { return callback(e, null); };
45434     xhr.open(method, url, true);
45435     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
45436     xhr.send(data);
45437     return xhr;
45438 };
45439
45440 ohauth$1.xhr = function(method, url, auth, data, options, callback) {
45441     var headers = (options && options.header) || {
45442         'Content-Type': 'application/x-www-form-urlencoded'
45443     };
45444     headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
45445     return ohauth$1.rawxhr(method, url, data, headers, callback);
45446 };
45447
45448 ohauth$1.nonce = function() {
45449     for (var o = ''; o.length < 6;) {
45450         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
45451     }
45452     return o;
45453 };
45454
45455 ohauth$1.authHeader = function(obj) {
45456     return Object.keys(obj).sort().map(function(key) {
45457         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
45458     }).join(', ');
45459 };
45460
45461 ohauth$1.timestamp = function() { return ~~((+new Date()) / 1000); };
45462
45463 ohauth$1.percentEncode = function(s) {
45464     return encodeURIComponent(s)
45465         .replace(/\!/g, '%21').replace(/\'/g, '%27')
45466         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
45467 };
45468
45469 ohauth$1.baseString = function(method, url, params) {
45470     if (params.oauth_signature) delete params.oauth_signature;
45471     return [
45472         method,
45473         ohauth$1.percentEncode(url),
45474         ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
45475 };
45476
45477 ohauth$1.signature = function(oauth_secret, token_secret, baseString) {
45478     return sha1.b64_hmac(
45479         ohauth$1.percentEncode(oauth_secret) + '&' +
45480         ohauth$1.percentEncode(token_secret),
45481         baseString);
45482 };
45483
45484 /**
45485  * Takes an options object for configuration (consumer_key,
45486  * consumer_secret, version, signature_method, token, token_secret)
45487  * and returns a function that generates the Authorization header
45488  * for given data.
45489  *
45490  * The returned function takes these parameters:
45491  * - method: GET/POST/...
45492  * - uri: full URI with protocol, port, path and query string
45493  * - extra_params: any extra parameters (that are passed in the POST data),
45494  *   can be an object or a from-urlencoded string.
45495  *
45496  * Returned function returns full OAuth header with "OAuth" string in it.
45497  */
45498
45499 ohauth$1.headerGenerator = function(options) {
45500     options = options || {};
45501     var consumer_key = options.consumer_key || '',
45502         consumer_secret = options.consumer_secret || '',
45503         signature_method = options.signature_method || 'HMAC-SHA1',
45504         version = options.version || '1.0',
45505         token = options.token || '',
45506         token_secret = options.token_secret || '';
45507
45508     return function(method, uri, extra_params) {
45509         method = method.toUpperCase();
45510         if (typeof extra_params === 'string' && extra_params.length > 0) {
45511             extra_params = ohauth$1.stringQs(extra_params);
45512         }
45513
45514         var uri_parts = uri.split('?', 2),
45515         base_uri = uri_parts[0];
45516
45517         var query_params = uri_parts.length === 2 ?
45518             ohauth$1.stringQs(uri_parts[1]) : {};
45519
45520         var oauth_params = {
45521             oauth_consumer_key: consumer_key,
45522             oauth_signature_method: signature_method,
45523             oauth_version: version,
45524             oauth_timestamp: ohauth$1.timestamp(),
45525             oauth_nonce: ohauth$1.nonce()
45526         };
45527
45528         if (token) oauth_params.oauth_token = token;
45529
45530         var all_params = xtend$1({}, oauth_params, query_params, extra_params),
45531             base_str = ohauth$1.baseString(method, base_uri, all_params);
45532
45533         oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
45534
45535         return 'OAuth ' + ohauth$1.authHeader(oauth_params);
45536     };
45537 };
45538
45539 var index$12 = ohauth$1;
45540
45541 var store$1 = createCommonjsModule(function (module, exports) {
45542 "use strict"
45543 // Module export pattern from
45544 // https://github.com/umdjs/umd/blob/master/returnExports.js
45545 ;(function (root, factory) {
45546     if (typeof define === 'function' && define.amd) {
45547         // AMD. Register as an anonymous module.
45548         define([], factory);
45549     } else if (typeof exports === 'object') {
45550         // Node. Does not work with strict CommonJS, but
45551         // only CommonJS-like environments that support module.exports,
45552         // like Node.
45553         module.exports = factory();
45554     } else {
45555         // Browser globals (root is window)
45556         root.store = factory();
45557   }
45558 }(commonjsGlobal, function () {
45559         
45560         // Store.js
45561         var store = {},
45562                 win = (typeof window != 'undefined' ? window : commonjsGlobal),
45563                 doc = win.document,
45564                 localStorageName = 'localStorage',
45565                 scriptTag = 'script',
45566                 storage;
45567
45568         store.disabled = false;
45569         store.version = '1.3.20';
45570         store.set = function(key, value) {};
45571         store.get = function(key, defaultVal) {};
45572         store.has = function(key) { return store.get(key) !== undefined };
45573         store.remove = function(key) {};
45574         store.clear = function() {};
45575         store.transact = function(key, defaultVal, transactionFn) {
45576                 if (transactionFn == null) {
45577                         transactionFn = defaultVal;
45578                         defaultVal = null;
45579                 }
45580                 if (defaultVal == null) {
45581                         defaultVal = {};
45582                 }
45583                 var val = store.get(key, defaultVal);
45584                 transactionFn(val);
45585                 store.set(key, val);
45586         };
45587         store.getAll = function() {};
45588         store.forEach = function() {};
45589
45590         store.serialize = function(value) {
45591                 return JSON.stringify(value)
45592         };
45593         store.deserialize = function(value) {
45594                 if (typeof value != 'string') { return undefined }
45595                 try { return JSON.parse(value) }
45596                 catch(e) { return value || undefined }
45597         };
45598
45599         // Functions to encapsulate questionable FireFox 3.6.13 behavior
45600         // when about.config::dom.storage.enabled === false
45601         // See https://github.com/marcuswestin/store.js/issues#issue/13
45602         function isLocalStorageNameSupported() {
45603                 try { return (localStorageName in win && win[localStorageName]) }
45604                 catch(err) { return false }
45605         }
45606
45607         if (isLocalStorageNameSupported()) {
45608                 storage = win[localStorageName];
45609                 store.set = function(key, val) {
45610                         if (val === undefined) { return store.remove(key) }
45611                         storage.setItem(key, store.serialize(val));
45612                         return val
45613                 };
45614                 store.get = function(key, defaultVal) {
45615                         var val = store.deserialize(storage.getItem(key));
45616                         return (val === undefined ? defaultVal : val)
45617                 };
45618                 store.remove = function(key) { storage.removeItem(key); };
45619                 store.clear = function() { storage.clear(); };
45620                 store.getAll = function() {
45621                         var ret = {};
45622                         store.forEach(function(key, val) {
45623                                 ret[key] = val;
45624                         });
45625                         return ret
45626                 };
45627                 store.forEach = function(callback) {
45628                         for (var i=0; i<storage.length; i++) {
45629                                 var key = storage.key(i);
45630                                 callback(key, store.get(key));
45631                         }
45632                 };
45633         } else if (doc && doc.documentElement.addBehavior) {
45634                 var storageOwner,
45635                         storageContainer;
45636                 // Since #userData storage applies only to specific paths, we need to
45637                 // somehow link our data to a specific path.  We choose /favicon.ico
45638                 // as a pretty safe option, since all browsers already make a request to
45639                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
45640                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
45641                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
45642                 // since the iframe access rules appear to allow direct access and
45643                 // manipulation of the document element, even for a 404 page.  This
45644                 // document can be used instead of the current document (which would
45645                 // have been limited to the current path) to perform #userData storage.
45646                 try {
45647                         storageContainer = new ActiveXObject('htmlfile');
45648                         storageContainer.open();
45649                         storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
45650                         storageContainer.close();
45651                         storageOwner = storageContainer.w.frames[0].document;
45652                         storage = storageOwner.createElement('div');
45653                 } catch(e) {
45654                         // somehow ActiveXObject instantiation failed (perhaps some special
45655                         // security settings or otherwse), fall back to per-path storage
45656                         storage = doc.createElement('div');
45657                         storageOwner = doc.body;
45658                 }
45659                 var withIEStorage = function(storeFunction) {
45660                         return function() {
45661                                 var args = Array.prototype.slice.call(arguments, 0);
45662                                 args.unshift(storage);
45663                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
45664                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
45665                                 storageOwner.appendChild(storage);
45666                                 storage.addBehavior('#default#userData');
45667                                 storage.load(localStorageName);
45668                                 var result = storeFunction.apply(store, args);
45669                                 storageOwner.removeChild(storage);
45670                                 return result
45671                         }
45672                 };
45673
45674                 // In IE7, keys cannot start with a digit or contain certain chars.
45675                 // See https://github.com/marcuswestin/store.js/issues/40
45676                 // See https://github.com/marcuswestin/store.js/issues/83
45677                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
45678                 var ieKeyFix = function(key) {
45679                         return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
45680                 };
45681                 store.set = withIEStorage(function(storage, key, val) {
45682                         key = ieKeyFix(key);
45683                         if (val === undefined) { return store.remove(key) }
45684                         storage.setAttribute(key, store.serialize(val));
45685                         storage.save(localStorageName);
45686                         return val
45687                 });
45688                 store.get = withIEStorage(function(storage, key, defaultVal) {
45689                         key = ieKeyFix(key);
45690                         var val = store.deserialize(storage.getAttribute(key));
45691                         return (val === undefined ? defaultVal : val)
45692                 });
45693                 store.remove = withIEStorage(function(storage, key) {
45694                         key = ieKeyFix(key);
45695                         storage.removeAttribute(key);
45696                         storage.save(localStorageName);
45697                 });
45698                 store.clear = withIEStorage(function(storage) {
45699                         var attributes = storage.XMLDocument.documentElement.attributes;
45700                         storage.load(localStorageName);
45701                         for (var i=attributes.length-1; i>=0; i--) {
45702                                 storage.removeAttribute(attributes[i].name);
45703                         }
45704                         storage.save(localStorageName);
45705                 });
45706                 store.getAll = function(storage) {
45707                         var ret = {};
45708                         store.forEach(function(key, val) {
45709                                 ret[key] = val;
45710                         });
45711                         return ret
45712                 };
45713                 store.forEach = withIEStorage(function(storage, callback) {
45714                         var attributes = storage.XMLDocument.documentElement.attributes;
45715                         for (var i=0, attr; attr=attributes[i]; ++i) {
45716                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
45717                         }
45718                 });
45719         }
45720
45721         try {
45722                 var testKey = '__storejs__';
45723                 store.set(testKey, testKey);
45724                 if (store.get(testKey) != testKey) { store.disabled = true; }
45725                 store.remove(testKey);
45726         } catch(e) {
45727                 store.disabled = true;
45728         }
45729         store.enabled = !store.disabled;
45730         
45731         return store
45732 }));
45733 });
45734
45735 var ohauth = index$12;
45736 var xtend = immutable;
45737 var store = store$1;
45738
45739 // # osm-auth
45740 //
45741 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
45742 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
45743 // does not support custom headers, which this uses everywhere.
45744 var index$11 = function(o) {
45745
45746     var oauth = {};
45747
45748     // authenticated users will also have a request token secret, but it's
45749     // not used in transactions with the server
45750     oauth.authenticated = function() {
45751         return !!(token('oauth_token') && token('oauth_token_secret'));
45752     };
45753
45754     oauth.logout = function() {
45755         token('oauth_token', '');
45756         token('oauth_token_secret', '');
45757         token('oauth_request_token_secret', '');
45758         return oauth;
45759     };
45760
45761     // TODO: detect lack of click event
45762     oauth.authenticate = function(callback) {
45763         if (oauth.authenticated()) return callback();
45764
45765         oauth.logout();
45766
45767         // ## Getting a request token
45768         var params = timenonce(getAuth(o)),
45769             url = o.url + '/oauth/request_token';
45770
45771         params.oauth_signature = ohauth.signature(
45772             o.oauth_secret, '',
45773             ohauth.baseString('POST', url, params));
45774
45775         if (!o.singlepage) {
45776             // Create a 600x550 popup window in the center of the screen
45777             var w = 600, h = 550,
45778                 settings = [
45779                     ['width', w], ['height', h],
45780                     ['left', screen.width / 2 - w / 2],
45781                     ['top', screen.height / 2 - h / 2]].map(function(x) {
45782                         return x.join('=');
45783                     }).join(','),
45784                 popup = window.open('about:blank', 'oauth_window', settings);
45785         }
45786
45787         // Request a request token. When this is complete, the popup
45788         // window is redirected to OSM's authorization page.
45789         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
45790         o.loading();
45791
45792         function reqTokenDone(err, xhr) {
45793             o.done();
45794             if (err) return callback(err);
45795             var resp = ohauth.stringQs(xhr.response);
45796             token('oauth_request_token_secret', resp.oauth_token_secret);
45797             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
45798                 oauth_token: resp.oauth_token,
45799                 oauth_callback: location.href.replace('index.html', '')
45800                     .replace(/#.*/, '').replace(location.search, '') + o.landing
45801             });
45802
45803             if (o.singlepage) {
45804                 location.href = authorize_url;
45805             } else {
45806                 popup.location = authorize_url;
45807             }
45808         }
45809
45810         // Called by a function in a landing page, in the popup window. The
45811         // window closes itself.
45812         window.authComplete = function(token) {
45813             var oauth_token = ohauth.stringQs(token.split('?')[1]);
45814             get_access_token(oauth_token.oauth_token);
45815             delete window.authComplete;
45816         };
45817
45818         // ## Getting an request token
45819         //
45820         // At this point we have an `oauth_token`, brought in from a function
45821         // call on a landing page popup.
45822         function get_access_token(oauth_token) {
45823             var url = o.url + '/oauth/access_token',
45824                 params = timenonce(getAuth(o)),
45825                 request_token_secret = token('oauth_request_token_secret');
45826             params.oauth_token = oauth_token;
45827             params.oauth_signature = ohauth.signature(
45828                 o.oauth_secret,
45829                 request_token_secret,
45830                 ohauth.baseString('POST', url, params));
45831
45832             // ## Getting an access token
45833             //
45834             // The final token required for authentication. At this point
45835             // we have a `request token secret`
45836             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
45837             o.loading();
45838         }
45839
45840         function accessTokenDone(err, xhr) {
45841             o.done();
45842             if (err) return callback(err);
45843             var access_token = ohauth.stringQs(xhr.response);
45844             token('oauth_token', access_token.oauth_token);
45845             token('oauth_token_secret', access_token.oauth_token_secret);
45846             callback(null, oauth);
45847         }
45848     };
45849
45850     oauth.bootstrapToken = function(oauth_token, callback) {
45851         // ## Getting an request token
45852         // At this point we have an `oauth_token`, brought in from a function
45853         // call on a landing page popup.
45854         function get_access_token(oauth_token) {
45855             var url = o.url + '/oauth/access_token',
45856                 params = timenonce(getAuth(o)),
45857                 request_token_secret = token('oauth_request_token_secret');
45858             params.oauth_token = oauth_token;
45859             params.oauth_signature = ohauth.signature(
45860                 o.oauth_secret,
45861                 request_token_secret,
45862                 ohauth.baseString('POST', url, params));
45863
45864             // ## Getting an access token
45865             // The final token required for authentication. At this point
45866             // we have a `request token secret`
45867             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
45868             o.loading();
45869         }
45870
45871         function accessTokenDone(err, xhr) {
45872             o.done();
45873             if (err) return callback(err);
45874             var access_token = ohauth.stringQs(xhr.response);
45875             token('oauth_token', access_token.oauth_token);
45876             token('oauth_token_secret', access_token.oauth_token_secret);
45877             callback(null, oauth);
45878         }
45879
45880         get_access_token(oauth_token);
45881     };
45882
45883     // # xhr
45884     //
45885     // A single XMLHttpRequest wrapper that does authenticated calls if the
45886     // user has logged in.
45887     oauth.xhr = function(options, callback) {
45888         if (!oauth.authenticated()) {
45889             if (o.auto) {
45890                 return oauth.authenticate(run);
45891             } else {
45892                 callback('not authenticated', null);
45893                 return;
45894             }
45895         } else {
45896             return run();
45897         }
45898
45899         function run() {
45900             var params = timenonce(getAuth(o)),
45901                 oauth_token_secret = token('oauth_token_secret'),
45902                 url = (options.prefix !== false) ? o.url + options.path : options.path,
45903                 url_parts = url.replace(/#.*$/, '').split('?', 2),
45904                 base_url = url_parts[0],
45905                 query = (url_parts.length === 2) ? url_parts[1] : '';
45906
45907             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
45908             if ((!options.options || !options.options.header ||
45909                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
45910                 options.content) {
45911                 params = xtend(params, ohauth.stringQs(options.content));
45912             }
45913
45914             params.oauth_token = token('oauth_token');
45915             params.oauth_signature = ohauth.signature(
45916                 o.oauth_secret,
45917                 oauth_token_secret,
45918                 ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query)))
45919             );
45920
45921             return ohauth.xhr(options.method, url, params, options.content, options.options, done);
45922         }
45923
45924         function done(err, xhr) {
45925             if (err) return callback(err);
45926             else if (xhr.responseXML) return callback(err, xhr.responseXML);
45927             else return callback(err, xhr.response);
45928         }
45929     };
45930
45931     // pre-authorize this object, if we can just get a token and token_secret
45932     // from the start
45933     oauth.preauth = function(c) {
45934         if (!c) return;
45935         if (c.oauth_token) token('oauth_token', c.oauth_token);
45936         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
45937         return oauth;
45938     };
45939
45940     oauth.options = function(_) {
45941         if (!arguments.length) return o;
45942
45943         o = _;
45944         o.url = o.url || 'http://www.openstreetmap.org';
45945         o.landing = o.landing || 'land.html';
45946         o.singlepage = o.singlepage || false;
45947
45948         // Optional loading and loading-done functions for nice UI feedback.
45949         // by default, no-ops
45950         o.loading = o.loading || function() {};
45951         o.done = o.done || function() {};
45952
45953         return oauth.preauth(o);
45954     };
45955
45956     // 'stamp' an authentication object from `getAuth()`
45957     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
45958     // and timestamp
45959     function timenonce(o) {
45960         o.oauth_timestamp = ohauth.timestamp();
45961         o.oauth_nonce = ohauth.nonce();
45962         return o;
45963     }
45964
45965     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
45966     // can be used with multiple APIs and the keys in `localStorage`
45967     // will not clash
45968     var token;
45969
45970     if (store.enabled) {
45971         token = function (x, y) {
45972             if (arguments.length === 1) return store.get(o.url + x);
45973             else if (arguments.length === 2) return store.set(o.url + x, y);
45974         };
45975     } else {
45976         var storage = {};
45977         token = function (x, y) {
45978             if (arguments.length === 1) return storage[o.url + x];
45979             else if (arguments.length === 2) return storage[o.url + x] = y;
45980         };
45981     }
45982
45983     // Get an authentication object. If you just add and remove properties
45984     // from a single object, you'll need to use `delete` to make sure that
45985     // it doesn't contain undesired properties for authentication
45986     function getAuth(o) {
45987         return {
45988             oauth_consumer_key: o.oauth_consumer_key,
45989             oauth_signature_method: 'HMAC-SHA1'
45990         };
45991     }
45992
45993     // potentially pre-authorize
45994     oauth.options(o);
45995
45996     return oauth;
45997 };
45998
45999 var JXON = new (function () {
46000   var
46001     sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
46002     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
46003
46004   function parseText (sValue) {
46005     if (rIsNull.test(sValue)) { return null; }
46006     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
46007     if (isFinite(sValue)) { return parseFloat(sValue); }
46008     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
46009     return sValue;
46010   }
46011
46012   function EmptyTree () { }
46013   EmptyTree.prototype.toString = function () { return 'null'; };
46014   EmptyTree.prototype.valueOf = function () { return null; };
46015
46016   function objectify (vValue) {
46017     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
46018   }
46019
46020   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
46021     var
46022       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
46023       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
46024
46025     var
46026       sProp, vContent, nLength = 0, sCollectedTxt = '',
46027       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46028
46029     if (bChildren) {
46030       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46031         oNode = oParentNode.childNodes.item(nItem);
46032         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46033         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46034         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46035       }
46036     }
46037
46038     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46039
46040     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46041
46042     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46043       sProp = aCache[nElId].nodeName.toLowerCase();
46044       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46045       if (vResult.hasOwnProperty(sProp)) {
46046         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46047         vResult[sProp].push(vContent);
46048       } else {
46049         vResult[sProp] = vContent;
46050         nLength++;
46051       }
46052     }
46053
46054     if (bAttributes) {
46055       var
46056         nAttrLen = oParentNode.attributes.length,
46057         sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46058
46059       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46060         oAttrib = oParentNode.attributes.item(nAttrib);
46061         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46062       }
46063
46064       if (bNesteAttr) {
46065         if (bFreeze) { Object.freeze(oAttrParent); }
46066         vResult[sAttributesProp] = oAttrParent;
46067         nLength -= nAttrLen - 1;
46068       }
46069     }
46070
46071     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46072       vResult[sValueProp] = vBuiltVal;
46073     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46074       vResult = vBuiltVal;
46075     }
46076
46077     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46078
46079     aCache.length = nLevelStart;
46080
46081     return vResult;
46082   }
46083
46084   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46085     var vValue, oChild;
46086
46087     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46088       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46089     } else if (oParentObj.constructor === Date) {
46090       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
46091     }
46092
46093     for (var sName in oParentObj) {
46094       vValue = oParentObj[sName];
46095       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46096       if (sName === sValueProp) {
46097         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46098       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46099         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46100       } else if (sName.charAt(0) === sAttrPref) {
46101         oParentEl.setAttribute(sName.slice(1), vValue);
46102       } else if (vValue.constructor === Array) {
46103         for (var nItem = 0; nItem < vValue.length; nItem++) {
46104           oChild = oXMLDoc.createElement(sName);
46105           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46106           oParentEl.appendChild(oChild);
46107         }
46108       } else {
46109         oChild = oXMLDoc.createElement(sName);
46110         if (vValue instanceof Object) {
46111           loadObjTree(oXMLDoc, oChild, vValue);
46112         } else if (vValue !== null && vValue !== true) {
46113           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46114         }
46115         oParentEl.appendChild(oChild);
46116      }
46117    }
46118   }
46119
46120   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46121     var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46122     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
46123   };
46124
46125   this.unbuild = function (oObjTree) {    
46126     var oNewDoc = document.implementation.createDocument('', '', null);
46127     loadObjTree(oNewDoc, oNewDoc, oObjTree);
46128     return oNewDoc;
46129   };
46130
46131   this.stringify = function (oObjTree) {
46132     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46133   };
46134 })();
46135
46136 // var myObject = JXON.build(doc);
46137 // we got our javascript object! try: alert(JSON.stringify(myObject));
46138
46139 // var newDoc = JXON.unbuild(myObject);
46140 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46141
46142 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46143 var useHttps = window.location.protocol === 'https:';
46144 var protocol = useHttps ? 'https:' : 'http:';
46145 var urlroot = protocol + '//www.openstreetmap.org';
46146 var inflight = {};
46147 var loadedTiles = {};
46148 var tileZoom$1 = 16;
46149 var oauth = index$11({
46150         url: urlroot,
46151         oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46152         oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46153         loading: authLoading,
46154         done: authDone
46155     });
46156 var rateLimitError;
46157 var userDetails;
46158 var off;
46159
46160
46161 function authLoading() {
46162     dispatch$3.call('authLoading');
46163 }
46164
46165
46166 function authDone() {
46167     dispatch$3.call('authDone');
46168 }
46169
46170
46171 function abortRequest$1(i) {
46172     if (i) {
46173         i.abort();
46174     }
46175 }
46176
46177
46178 function getLoc(attrs) {
46179     var lon = attrs.lon && attrs.lon.value,
46180         lat = attrs.lat && attrs.lat.value;
46181     return [parseFloat(lon), parseFloat(lat)];
46182 }
46183
46184
46185 function getNodes(obj) {
46186     var elems = obj.getElementsByTagName('nd'),
46187         nodes = new Array(elems.length);
46188     for (var i = 0, l = elems.length; i < l; i++) {
46189         nodes[i] = 'n' + elems[i].attributes.ref.value;
46190     }
46191     return nodes;
46192 }
46193
46194
46195 function getTags(obj) {
46196     var elems = obj.getElementsByTagName('tag'),
46197         tags = {};
46198     for (var i = 0, l = elems.length; i < l; i++) {
46199         var attrs = elems[i].attributes;
46200         tags[attrs.k.value] = attrs.v.value;
46201     }
46202     return tags;
46203 }
46204
46205
46206 function getMembers(obj) {
46207     var elems = obj.getElementsByTagName('member'),
46208         members = new Array(elems.length);
46209     for (var i = 0, l = elems.length; i < l; i++) {
46210         var attrs = elems[i].attributes;
46211         members[i] = {
46212             id: attrs.type.value[0] + attrs.ref.value,
46213             type: attrs.type.value,
46214             role: attrs.role.value
46215         };
46216     }
46217     return members;
46218 }
46219
46220
46221 function getVisible(attrs) {
46222     return (!attrs.visible || attrs.visible.value !== 'false');
46223 }
46224
46225
46226 var parsers = {
46227     node: function nodeData(obj) {
46228         var attrs = obj.attributes;
46229         return new osmNode({
46230             id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46231             loc: getLoc(attrs),
46232             version: attrs.version.value,
46233             user: attrs.user && attrs.user.value,
46234             tags: getTags(obj),
46235             visible: getVisible(attrs)
46236         });
46237     },
46238
46239     way: function wayData(obj) {
46240         var attrs = obj.attributes;
46241         return new osmWay({
46242             id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46243             version: attrs.version.value,
46244             user: attrs.user && attrs.user.value,
46245             tags: getTags(obj),
46246             nodes: getNodes(obj),
46247             visible: getVisible(attrs)
46248         });
46249     },
46250
46251     relation: function relationData(obj) {
46252         var attrs = obj.attributes;
46253         return new osmRelation({
46254             id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
46255             version: attrs.version.value,
46256             user: attrs.user && attrs.user.value,
46257             tags: getTags(obj),
46258             members: getMembers(obj),
46259             visible: getVisible(attrs)
46260         });
46261     }
46262 };
46263
46264
46265 function parse(xml$$1) {
46266     if (!xml$$1 || !xml$$1.childNodes) return;
46267
46268     var root = xml$$1.childNodes[0],
46269         children = root.childNodes,
46270         entities = [];
46271
46272     for (var i = 0, l = children.length; i < l; i++) {
46273         var child = children[i],
46274             parser = parsers[child.nodeName];
46275         if (parser) {
46276             entities.push(parser(child));
46277         }
46278     }
46279
46280     return entities;
46281 }
46282
46283
46284 var serviceOsm = {
46285
46286     init: function() {
46287         utilRebind(this, dispatch$3, 'on');
46288     },
46289
46290
46291     reset: function() {
46292         userDetails = undefined;
46293         rateLimitError = undefined;
46294         lodash.forEach(inflight, abortRequest$1);
46295         loadedTiles = {};
46296         inflight = {};
46297         return this;
46298     },
46299
46300
46301     changesetURL: function(changesetId) {
46302         return urlroot + '/changeset/' + changesetId;
46303     },
46304
46305
46306     changesetsURL: function(center, zoom$$1) {
46307         var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
46308         return urlroot + '/history#map=' +
46309             Math.floor(zoom$$1) + '/' +
46310             center[1].toFixed(precision) + '/' +
46311             center[0].toFixed(precision);
46312     },
46313
46314
46315     entityURL: function(entity) {
46316         return urlroot + '/' + entity.type + '/' + entity.osmId();
46317     },
46318
46319
46320     userURL: function(username) {
46321         return urlroot + '/user/' + username;
46322     },
46323
46324
46325     loadFromAPI: function(path$$1, callback) {
46326         var that = this;
46327
46328         function done(err, xml$$1) {
46329             var isAuthenticated = that.authenticated();
46330
46331             // 400 Bad Request, 401 Unauthorized, 403 Forbidden
46332             // Logout and retry the request..
46333             if (isAuthenticated && err &&
46334                     (err.status === 400 || err.status === 401 || err.status === 403)) {
46335                 that.logout();
46336                 that.loadFromAPI(path$$1, callback);
46337
46338             // else, no retry..
46339             } else {
46340                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
46341                 // Set the rateLimitError flag and trigger a warning..
46342                 if (!isAuthenticated && !rateLimitError && err &&
46343                         (err.status === 509 || err.status === 429)) {
46344                     rateLimitError = err;
46345                     dispatch$3.call('change');
46346                 }
46347
46348                 if (callback) {
46349                     callback(err, parse(xml$$1));
46350                 }
46351             }
46352         }
46353
46354         if (this.authenticated()) {
46355             return oauth.xhr({ method: 'GET', path: path$$1 }, done);
46356         } else {
46357             var url = urlroot + path$$1;
46358             return xml(url).get(done);
46359         }
46360     },
46361
46362
46363     loadEntity: function(id, callback) {
46364         var type = osmEntity$$1.id.type(id),
46365             osmID = osmEntity$$1.id.toOSM(id);
46366
46367         this.loadFromAPI(
46368             '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
46369             function(err, entities) {
46370                 if (callback) callback(err, { data: entities });
46371             }
46372         );
46373     },
46374
46375
46376     loadEntityVersion: function(id, version$$1, callback) {
46377         var type = osmEntity$$1.id.type(id),
46378             osmID = osmEntity$$1.id.toOSM(id);
46379
46380         this.loadFromAPI(
46381             '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
46382             function(err, entities) {
46383                 if (callback) callback(err, { data: entities });
46384             }
46385         );
46386     },
46387
46388
46389     loadMultiple: function(ids, callback) {
46390         var that = this;
46391         lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
46392             var type = k + 's',
46393                 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
46394
46395             lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
46396                 that.loadFromAPI(
46397                     '/api/0.6/' + type + '?' + type + '=' + arr.join(),
46398                     function(err, entities) {
46399                         if (callback) callback(err, { data: entities });
46400                     }
46401                 );
46402             });
46403         });
46404     },
46405
46406
46407     authenticated: function() {
46408         return oauth.authenticated();
46409     },
46410
46411
46412     // Generate Changeset XML. Returns a string.
46413     changesetJXON: function(tags) {
46414         return {
46415             osm: {
46416                 changeset: {
46417                     tag: lodash.map(tags, function(value, key) {
46418                         return { '@k': key, '@v': value };
46419                     }),
46420                     '@version': 0.6,
46421                     '@generator': 'iD'
46422                 }
46423             }
46424         };
46425     },
46426
46427
46428     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
46429     // XML. Returns a string.
46430     osmChangeJXON: function(changeset_id, changes) {
46431         function nest$$1(x, order) {
46432             var groups = {};
46433             for (var i = 0; i < x.length; i++) {
46434                 var tagName = Object.keys(x[i])[0];
46435                 if (!groups[tagName]) groups[tagName] = [];
46436                 groups[tagName].push(x[i][tagName]);
46437             }
46438             var ordered = {};
46439             order.forEach(function(o) {
46440                 if (groups[o]) ordered[o] = groups[o];
46441             });
46442             return ordered;
46443         }
46444
46445         function rep(entity) {
46446             return entity.asJXON(changeset_id);
46447         }
46448
46449         return {
46450             osmChange: {
46451                 '@version': 0.6,
46452                 '@generator': 'iD',
46453                 'create': nest$$1(changes.created.map(rep), ['node', 'way', 'relation']),
46454                 'modify': nest$$1(changes.modified.map(rep), ['node', 'way', 'relation']),
46455                 'delete': lodash.extend(nest$$1(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
46456             }
46457         };
46458     },
46459
46460
46461     changesetTags: function(version$$1, comment, imageryUsed) {
46462         var detected = utilDetect(),
46463             tags = {
46464                 created_by: ('iD ' + version$$1).substr(0, 255),
46465                 imagery_used: imageryUsed.join(';').substr(0, 255),
46466                 host: detected.host.substr(0, 255),
46467                 locale: detected.locale.substr(0, 255)
46468             };
46469
46470         if (comment) {
46471             tags.comment = comment.substr(0, 255);
46472         }
46473
46474         return tags;
46475     },
46476
46477
46478     putChangeset: function(changes, version$$1, comment, imageryUsed, callback) {
46479         var that = this;
46480         oauth.xhr({
46481                 method: 'PUT',
46482                 path: '/api/0.6/changeset/create',
46483                 options: { header: { 'Content-Type': 'text/xml' } },
46484                 content: JXON.stringify(that.changesetJXON(that.changesetTags(version$$1, comment, imageryUsed)))
46485             }, function(err, changeset_id) {
46486                 if (err) return callback(err);
46487                 oauth.xhr({
46488                     method: 'POST',
46489                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
46490                     options: { header: { 'Content-Type': 'text/xml' } },
46491                     content: JXON.stringify(that.osmChangeJXON(changeset_id, changes))
46492                 }, function(err) {
46493                     if (err) return callback(err);
46494                     // POST was successful, safe to call the callback.
46495                     // Still attempt to close changeset, but ignore response because #2667
46496                     // Add delay to allow for postgres replication #1646 #2678
46497                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
46498                     oauth.xhr({
46499                         method: 'PUT',
46500                         path: '/api/0.6/changeset/' + changeset_id + '/close',
46501                         options: { header: { 'Content-Type': 'text/xml' } }
46502                     }, function() { return true; });
46503                 });
46504             });
46505     },
46506
46507
46508     userDetails: function(callback) {
46509         if (userDetails) {
46510             callback(undefined, userDetails);
46511             return;
46512         }
46513
46514         function done(err, user_details) {
46515             if (err) return callback(err);
46516
46517             var u = user_details.getElementsByTagName('user')[0],
46518                 img = u.getElementsByTagName('img'),
46519                 image_url = '';
46520
46521             if (img && img[0] && img[0].getAttribute('href')) {
46522                 image_url = img[0].getAttribute('href');
46523             }
46524
46525             userDetails = {
46526                 display_name: u.attributes.display_name.value,
46527                 image_url: image_url,
46528                 id: u.attributes.id.value
46529             };
46530
46531             callback(undefined, userDetails);
46532         }
46533
46534         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
46535     },
46536
46537
46538     userChangesets: function(callback) {
46539         this.userDetails(function(err, user) {
46540             if (err) {
46541                 callback(err);
46542                 return;
46543             }
46544
46545             function done(err, changesets) {
46546                 if (err) {
46547                     callback(err);
46548                 } else {
46549                     callback(undefined, Array.prototype.map.call(changesets.getElementsByTagName('changeset'),
46550                         function (changeset) {
46551                             return { tags: getTags(changeset) };
46552                         }
46553                     ));
46554                 }
46555             }
46556
46557             oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
46558         });
46559     },
46560
46561
46562     status: function(callback) {
46563         function done(capabilities) {
46564             if (rateLimitError) {
46565                 callback(rateLimitError, 'rateLimited');
46566             } else {
46567                 var apiStatus = capabilities.getElementsByTagName('status'),
46568                     val = apiStatus[0].getAttribute('api');
46569                 callback(undefined, val);
46570             }
46571         }
46572         xml(urlroot + '/api/capabilities').get()
46573             .on('load', done)
46574             .on('error', callback);
46575     },
46576
46577
46578     tileZoom: function(_) {
46579         if (!arguments.length) return tileZoom$1;
46580         tileZoom$1 = _;
46581         return this;
46582     },
46583
46584
46585     loadTiles: function(projection, dimensions, callback) {
46586         if (off) return;
46587
46588         var that = this,
46589             s = projection.scale() * 2 * Math.PI,
46590             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
46591             ts = 256 * Math.pow(2, z - tileZoom$1),
46592             origin = [
46593                 s / 2 - projection.translate()[0],
46594                 s / 2 - projection.translate()[1]
46595             ];
46596
46597         var tiles = d3geoTile()
46598             .scaleExtent([tileZoom$1, tileZoom$1])
46599             .scale(s)
46600             .size(dimensions)
46601             .translate(projection.translate())()
46602             .map(function(tile) {
46603                 var x = tile[0] * ts - origin[0],
46604                     y = tile[1] * ts - origin[1];
46605
46606                 return {
46607                     id: tile.toString(),
46608                     extent: geoExtent$$1(
46609                         projection.invert([x, y + ts]),
46610                         projection.invert([x + ts, y]))
46611                 };
46612             });
46613
46614         lodash.filter(inflight, function(v, i) {
46615             var wanted = lodash.find(tiles, function(tile) {
46616                 return i === tile.id;
46617             });
46618             if (!wanted) delete inflight[i];
46619             return !wanted;
46620         }).map(abortRequest$1);
46621
46622         tiles.forEach(function(tile) {
46623             var id = tile.id;
46624
46625             if (loadedTiles[id] || inflight[id]) return;
46626
46627             if (lodash.isEmpty(inflight)) {
46628                 dispatch$3.call('loading');
46629             }
46630
46631             inflight[id] = that.loadFromAPI(
46632                 '/api/0.6/map?bbox=' + tile.extent.toParam(),
46633                 function(err, parsed) {
46634                     delete inflight[id];
46635                     if (!err) {
46636                         loadedTiles[id] = true;
46637                     }
46638
46639                     if (callback) {
46640                         callback(err, lodash.extend({ data: parsed }, tile));
46641                     }
46642
46643                     if (lodash.isEmpty(inflight)) {
46644                         dispatch$3.call('loaded');
46645                     }
46646                 }
46647             );
46648         });
46649     },
46650
46651
46652     switch: function(options) {
46653         urlroot = options.urlroot;
46654
46655         oauth.options(lodash.extend({
46656             url: urlroot,
46657             loading: authLoading,
46658             done: authDone
46659         }, options));
46660         dispatch$3.call('change');
46661         this.reset();
46662         return this;
46663     },
46664
46665
46666     toggle: function(_) {
46667         off = !_;
46668         return this;
46669     },
46670
46671
46672     loadedTiles: function(_) {
46673         if (!arguments.length) return loadedTiles;
46674         loadedTiles = _;
46675         return this;
46676     },
46677
46678
46679     logout: function() {
46680         userDetails = undefined;
46681         oauth.logout();
46682         dispatch$3.call('change');
46683         return this;
46684     },
46685
46686
46687     authenticate: function(callback) {
46688         userDetails = undefined;
46689         function done(err, res) {
46690             rateLimitError = undefined;
46691             dispatch$3.call('change');
46692             if (callback) callback(err, res);
46693         }
46694         return oauth.authenticate(done);
46695     }
46696 };
46697
46698 var endpoint$1 = 'https://taginfo.openstreetmap.org/api/4/';
46699 var taginfoCache = {};
46700 var tag_sorts = {
46701         point: 'count_nodes',
46702         vertex: 'count_nodes',
46703         area: 'count_ways',
46704         line: 'count_ways'
46705     };
46706 var tag_sort_members = {
46707         point: 'count_node_members',
46708         vertex: 'count_node_members',
46709         area: 'count_way_members',
46710         line: 'count_way_members',
46711         relation: 'count_relation_members'
46712     };
46713 var tag_filters = {
46714         point: 'nodes',
46715         vertex: 'nodes',
46716         area: 'ways',
46717         line: 'ways'
46718     };
46719 var tag_members_fractions = {
46720         point: 'count_node_members_fraction',
46721         vertex: 'count_node_members_fraction',
46722         area: 'count_way_members_fraction',
46723         line: 'count_way_members_fraction',
46724         relation: 'count_relation_members_fraction'
46725     };
46726
46727
46728 function sets(parameters, n, o) {
46729     if (parameters.geometry && o[parameters.geometry]) {
46730         parameters[n] = o[parameters.geometry];
46731     }
46732     return parameters;
46733 }
46734
46735
46736 function setFilter(parameters) {
46737     return sets(parameters, 'filter', tag_filters);
46738 }
46739
46740
46741 function setSort(parameters) {
46742     return sets(parameters, 'sortname', tag_sorts);
46743 }
46744
46745
46746 function setSortMembers(parameters) {
46747     return sets(parameters, 'sortname', tag_sort_members);
46748 }
46749
46750
46751 function clean(parameters) {
46752     return lodash.omit(parameters, 'geometry', 'debounce');
46753 }
46754
46755
46756 function filterKeys(type) {
46757     var count_type = type ? 'count_' + type : 'count_all';
46758     return function(d) {
46759         return parseFloat(d[count_type]) > 2500 || d.in_wiki;
46760     };
46761 }
46762
46763
46764 function filterMultikeys(prefix) {
46765     return function(d) {
46766         // d.key begins with prefix, and d.key contains no additional ':'s
46767         var re = new RegExp('^' + prefix + '(.*)$');
46768         var matches = d.key.match(re) || [];
46769         return (matches.length === 2 && matches[1].indexOf(':') === -1);
46770     };
46771 }
46772
46773
46774 function filterValues(allowUpperCase) {
46775     return function(d) {
46776         if (d.value.match(/[;,]/) !== null) return false;  // exclude some punctuation
46777         if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false;  // exclude uppercase letters
46778         return parseFloat(d.fraction) > 0.0 || d.in_wiki;
46779     };
46780 }
46781
46782
46783 function filterRoles(geometry) {
46784     return function(d) {
46785         if (d.role === '') return false; // exclude empty role
46786         if (d.role.match(/[A-Z*;,]/) !== null) return false;  // exclude uppercase letters and some punctuation
46787         return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
46788     };
46789 }
46790
46791
46792 function valKey(d) {
46793     return {
46794         value: d.key,
46795         title: d.key
46796     };
46797 }
46798
46799
46800 function valKeyDescription(d) {
46801     return {
46802         value: d.value,
46803         title: d.description || d.value
46804     };
46805 }
46806
46807
46808 function roleKey(d) {
46809     return {
46810         value: d.role,
46811         title: d.role
46812     };
46813 }
46814
46815
46816 // sort keys with ':' lower than keys without ':'
46817 function sortKeys(a, b) {
46818     return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
46819         : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
46820         : 0;
46821 }
46822
46823
46824 var debounced = lodash.debounce(json, 100, true);
46825
46826
46827 function request$1(url, debounce, callback) {
46828     if (taginfoCache[url]) {
46829         callback(null, taginfoCache[url]);
46830     } else if (debounce) {
46831         debounced(url, done);
46832     } else {
46833         json(url, done);
46834     }
46835
46836     function done(err, data) {
46837         if (!err) {
46838             taginfoCache[url] = data;
46839         }
46840         callback(err, data);
46841     }
46842 }
46843
46844
46845 var serviceTaginfo = {
46846
46847     init: function() { taginfoCache = {}; },
46848     reset: function() { taginfoCache = {}; },
46849
46850
46851     keys: function(parameters, callback) {
46852         var debounce = parameters.debounce;
46853         parameters = clean(setSort(parameters));
46854         request$1(endpoint$1 + 'keys/all?' +
46855             utilQsString(lodash.extend({
46856                 rp: 10,
46857                 sortname: 'count_all',
46858                 sortorder: 'desc',
46859                 page: 1
46860             }, parameters)), debounce, function(err, d) {
46861                 if (err) {
46862                     callback(err);
46863                 } else {
46864                     var f = filterKeys(parameters.filter);
46865                     callback(null, d.data.filter(f).sort(sortKeys).map(valKey));
46866                 }
46867             }
46868         );
46869     },
46870
46871
46872     multikeys: function(parameters, callback) {
46873         var debounce = parameters.debounce;
46874         parameters = clean(setSort(parameters));
46875         var prefix = parameters.query;
46876         request$1(endpoint$1 + 'keys/all?' +
46877             utilQsString(lodash.extend({
46878                 rp: 25,
46879                 sortname: 'count_all',
46880                 sortorder: 'desc',
46881                 page: 1
46882             }, parameters)), debounce, function(err, d) {
46883                 if (err) {
46884                     callback(err);
46885                 } else {
46886                     var f = filterMultikeys(prefix);
46887                     callback(null, d.data.filter(f).map(valKey));
46888                 }
46889             }
46890         );
46891     },
46892
46893
46894     values: function(parameters, callback) {
46895         var debounce = parameters.debounce;
46896         parameters = clean(setSort(setFilter(parameters)));
46897         request$1(endpoint$1 + 'key/values?' +
46898             utilQsString(lodash.extend({
46899                 rp: 25,
46900                 sortname: 'count_all',
46901                 sortorder: 'desc',
46902                 page: 1
46903             }, parameters)), debounce, function(err, d) {
46904                 if (err) {
46905                     callback(err);
46906                 } else {
46907                     // In most cases we prefer taginfo value results with lowercase letters.
46908                     // A few OSM keys expect values to contain uppercase values (see #3377).
46909                     // This is not an exhaustive list (e.g. `name` also has uppercase values)
46910                     // but these are the fields where taginfo value lookup is most useful.
46911                     var re = /network|taxon|genus|species/;
46912                     var allowUpperCase = (parameters.key.match(re) !== null);
46913                     var f = filterValues(allowUpperCase);
46914                     callback(null, d.data.filter(f).map(valKeyDescription));
46915                 }
46916             }
46917         );
46918     },
46919
46920
46921     roles: function(parameters, callback) {
46922         var debounce = parameters.debounce;
46923         var geometry = parameters.geometry;
46924         parameters = clean(setSortMembers(parameters));
46925         request$1(endpoint$1 + 'relation/roles?' +
46926             utilQsString(lodash.extend({
46927                 rp: 25,
46928                 sortname: 'count_all_members',
46929                 sortorder: 'desc',
46930                 page: 1
46931             }, parameters)), debounce, function(err, d) {
46932                 if (err) {
46933                     callback(err);
46934                 } else {
46935                     var f = filterRoles(geometry);
46936                     callback(null, d.data.filter(f).map(roleKey));
46937                 }
46938             }
46939         );
46940     },
46941
46942
46943     docs: function(parameters, callback) {
46944         var debounce = parameters.debounce;
46945         parameters = clean(setSort(parameters));
46946
46947         var path$$1 = 'key/wiki_pages?';
46948         if (parameters.value) path$$1 = 'tag/wiki_pages?';
46949         else if (parameters.rtype) path$$1 = 'relation/wiki_pages?';
46950
46951         request$1(endpoint$1 + path$$1 + utilQsString(parameters), debounce, function(err, d) {
46952             if (err) {
46953                 callback(err);
46954             } else {
46955                 callback(null, d.data);
46956             }
46957         });
46958     },
46959
46960
46961     endpoint: function(_) {
46962         if (!arguments.length) return endpoint$1;
46963         endpoint$1 = _;
46964         return this;
46965     }
46966
46967 };
46968
46969 var jsonpCache = {};
46970 window.jsonpCache = jsonpCache;
46971
46972 function jsonpRequest(url, callback) {
46973
46974   if (window.JSONP_FIX) {
46975     if (window.JSONP_DELAY === 0) {
46976       callback(window.JSONP_FIX);
46977     } else {
46978       setTimeout(function() {
46979         callback(window.JSONP_FIX);
46980       }, window.JSONP_DELAY || 0);
46981     }
46982     return;
46983   }
46984
46985   function rand() {
46986     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
46987       c = '', i = -1;
46988     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
46989     return c;
46990   }
46991
46992   function create(url) {
46993     var e = url.match(/callback=(\w+)/),
46994       c = e ? e[1] : rand();
46995     jsonpCache[c] = function(data) {
46996       callback(data);
46997       delete jsonpCache[c];
46998       script.remove();
46999     };
47000     return 'jsonpCache.' + c;
47001   }
47002
47003   var cb = create(url),
47004     script = select('head')
47005     .append('script')
47006     .attr('type', 'text/javascript')
47007     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
47008 }
47009
47010 var endpoint$2 = 'https://www.wikidata.org/w/api.php?';
47011
47012 var serviceWikidata = {
47013
47014     init: function() {},
47015     reset: function() {},
47016
47017
47018     // Given a Wikipedia language and article title, return an array of
47019     // corresponding Wikidata entities.
47020     itemsByTitle: function(lang, title, callback) {
47021         if (!title) {
47022             callback('', {});
47023             return;
47024         }
47025
47026         lang = lang || 'en';
47027         jsonpRequest(endpoint$2 + utilQsString({
47028             action: 'wbgetentities',
47029             format: 'json',
47030             sites: lang.replace(/-/g, '_') + 'wiki',
47031             titles: title,
47032             languages: 'en', // shrink response by filtering to one language
47033             callback: '{callback}'
47034         }), function(data) {
47035             if (!data || data.error) {
47036                 callback('', {});
47037             } else {
47038                 callback(title, data.entities || {});
47039             }
47040         });
47041     }
47042
47043 };
47044
47045 var endpoint$3 = 'https://en.wikipedia.org/w/api.php?';
47046
47047 var serviceWikipedia = {
47048
47049     init: function() {},
47050     reset: function() {},
47051
47052
47053     search: function(lang, query, callback) {
47054         if (!query) {
47055             callback('', []);
47056             return;
47057         }
47058
47059         lang = lang || 'en';
47060         jsonpRequest(endpoint$3.replace('en', lang) +
47061             utilQsString({
47062                 action: 'query',
47063                 list: 'search',
47064                 srlimit: '10',
47065                 srinfo: 'suggestion',
47066                 format: 'json',
47067                 callback: '{callback}',
47068                 srsearch: query
47069             }), function(data) {
47070                 if (!data || !data.query || !data.query.search || data.error) {
47071                     callback('', []);
47072                 } else {
47073                     var results = data.query.search.map(function(d) { return d.title; });
47074                     callback(query, results);
47075                 }
47076             }
47077         );
47078     },
47079
47080
47081     suggestions: function(lang, query, callback) {
47082         if (!query) {
47083             callback('', []);
47084             return;
47085         }
47086
47087         lang = lang || 'en';
47088         jsonpRequest(endpoint$3.replace('en', lang) +
47089             utilQsString({
47090                 action: 'opensearch',
47091                 namespace: 0,
47092                 suggest: '',
47093                 format: 'json',
47094                 callback: '{callback}',
47095                 search: query
47096             }), function(data) {
47097                 if (!data || data.error) {
47098                     callback('', []);
47099                 } else {
47100                     callback(data[0], data[1] || []);
47101                 }
47102             }
47103         );
47104     },
47105
47106
47107     translations: function(lang, title, callback) {
47108         if (!title) {
47109             callback({});
47110             return;
47111         }
47112
47113         jsonpRequest(endpoint$3.replace('en', lang) +
47114             utilQsString({
47115                 action: 'query',
47116                 prop: 'langlinks',
47117                 format: 'json',
47118                 callback: '{callback}',
47119                 lllimit: 500,
47120                 titles: title
47121             }), function(data) {
47122                 if (!data || !data.query || !data.query.pages || data.error) {
47123                     callback({});
47124                 } else {
47125                     var list = data.query.pages[Object.keys(data.query.pages)[0]],
47126                         translations = {};
47127                     if (list && list.langlinks) {
47128                         list.langlinks.forEach(function(d) {
47129                             translations[d.lang] = d['*'];
47130                         });
47131                     }
47132                     callback(translations);
47133                 }
47134             }
47135         );
47136     }
47137
47138 };
47139
47140 var services = {
47141     mapillary: serviceMapillary,
47142     nominatim: serviceNominatim,
47143     osm: serviceOsm,
47144     taginfo: serviceTaginfo,
47145     wikidata: serviceWikidata,
47146     wikipedia: serviceWikipedia
47147 };
47148
47149 function svgMapillaryImages(projection, context, dispatch$$1) {
47150     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47151         minZoom = 12,
47152         minViewfieldZoom = 17,
47153         layer = select(null),
47154         _mapillary;
47155
47156
47157     function init() {
47158         if (svgMapillaryImages.initialized) return;  // run once
47159         svgMapillaryImages.enabled = false;
47160         svgMapillaryImages.initialized = true;
47161     }
47162
47163
47164     function getMapillary() {
47165         if (services.mapillary && !_mapillary) {
47166             _mapillary = services.mapillary;
47167             _mapillary.event.on('loadedImages', throttledRedraw);
47168         } else if (!services.mapillary && _mapillary) {
47169             _mapillary = null;
47170         }
47171
47172         return _mapillary;
47173     }
47174
47175
47176     function showLayer() {
47177         var mapillary = getMapillary();
47178         if (!mapillary) return;
47179
47180         mapillary.loadViewer(context);
47181         editOn();
47182
47183         layer
47184             .style('opacity', 0)
47185             .transition()
47186             .duration(500)
47187             .style('opacity', 1)
47188             .on('end', function () { dispatch$$1.call('change'); });
47189     }
47190
47191
47192     function hideLayer() {
47193         var mapillary = getMapillary();
47194         if (mapillary) {
47195             mapillary.hideViewer();
47196         }
47197
47198         throttledRedraw.cancel();
47199
47200         layer
47201             .transition()
47202             .duration(500)
47203             .style('opacity', 0)
47204             .on('end', editOff);
47205     }
47206
47207
47208     function editOn() {
47209         layer.style('display', 'block');
47210     }
47211
47212
47213     function editOff() {
47214         layer.selectAll('.viewfield-group').remove();
47215         layer.style('display', 'none');
47216     }
47217
47218
47219     function click(d) {
47220         var mapillary = getMapillary();
47221         if (!mapillary) return;
47222
47223         context.map().centerEase(d.loc);
47224
47225         mapillary
47226             .selectedImage(d.key, true)
47227             .updateViewer(d.key, context)
47228             .showViewer();
47229     }
47230
47231
47232     function transform(d) {
47233         var t = svgPointTransform(projection)(d);
47234         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
47235         return t;
47236     }
47237
47238
47239     function update() {
47240         var mapillary = getMapillary(),
47241             data = (mapillary ? mapillary.images(projection) : []),
47242             imageKey = mapillary ? mapillary.selectedImage() : null;
47243
47244         var markers = layer.selectAll('.viewfield-group')
47245             .data(data, function(d) { return d.key; });
47246
47247         markers.exit()
47248             .remove();
47249
47250         var enter = markers.enter()
47251             .append('g')
47252             .attr('class', 'viewfield-group')
47253             .classed('selected', function(d) { return d.key === imageKey; })
47254             .on('click', click);
47255
47256         markers = markers
47257             .merge(enter)
47258             .attr('transform', transform);
47259
47260
47261        var viewfields = markers.selectAll('.viewfield')
47262             .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
47263
47264         viewfields.exit()
47265             .remove();
47266
47267         viewfields.enter()
47268             .append('path')
47269             .attr('class', 'viewfield')
47270             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
47271             .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');
47272
47273         markers.selectAll('circle')
47274             .data([0])
47275             .enter()
47276             .append('circle')
47277             .attr('dx', '0')
47278             .attr('dy', '0')
47279             .attr('r', '6');
47280     }
47281
47282
47283     function drawImages(selection$$1) {
47284         var enabled = svgMapillaryImages.enabled,
47285             mapillary = getMapillary();
47286
47287         layer = selection$$1.selectAll('.layer-mapillary-images')
47288             .data(mapillary ? [0] : []);
47289
47290         layer.exit()
47291             .remove();
47292
47293         layer = layer.enter()
47294             .append('g')
47295             .attr('class', 'layer-mapillary-images')
47296             .style('display', enabled ? 'block' : 'none')
47297             .merge(layer);
47298
47299         if (enabled) {
47300             if (mapillary && ~~context.map().zoom() >= minZoom) {
47301                 editOn();
47302                 update();
47303                 mapillary.loadImages(projection);
47304             } else {
47305                 editOff();
47306             }
47307         }
47308     }
47309
47310
47311     drawImages.enabled = function(_) {
47312         if (!arguments.length) return svgMapillaryImages.enabled;
47313         svgMapillaryImages.enabled = _;
47314         if (svgMapillaryImages.enabled) {
47315             showLayer();
47316         } else {
47317             hideLayer();
47318         }
47319         dispatch$$1.call('change');
47320         return this;
47321     };
47322
47323
47324     drawImages.supported = function() {
47325         return !!getMapillary();
47326     };
47327
47328
47329     init();
47330     return drawImages;
47331 }
47332
47333 function svgMapillarySigns(projection, context, dispatch$$1) {
47334     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47335         minZoom = 12,
47336         layer = select(null),
47337         _mapillary;
47338
47339
47340     function init() {
47341         if (svgMapillarySigns.initialized) return;  // run once
47342         svgMapillarySigns.enabled = false;
47343         svgMapillarySigns.initialized = true;
47344     }
47345
47346
47347     function getMapillary() {
47348         if (services.mapillary && !_mapillary) {
47349             _mapillary = services.mapillary;
47350             _mapillary.event.on('loadedSigns', throttledRedraw);
47351         } else if (!services.mapillary && _mapillary) {
47352             _mapillary = null;
47353         }
47354         return _mapillary;
47355     }
47356
47357
47358     function showLayer() {
47359         editOn();
47360     }
47361
47362
47363     function hideLayer() {
47364         throttledRedraw.cancel();
47365         editOff();
47366     }
47367
47368
47369     function editOn() {
47370         layer.style('display', 'block');
47371     }
47372
47373
47374     function editOff() {
47375         layer.selectAll('.icon-sign').remove();
47376         layer.style('display', 'none');
47377     }
47378
47379
47380     function click(d) {
47381         var mapillary = getMapillary();
47382         if (!mapillary) return;
47383
47384         context.map().centerEase(d.loc);
47385
47386         mapillary
47387             .selectedImage(d.key, true)
47388             .updateViewer(d.key, context)
47389             .showViewer();
47390     }
47391
47392
47393     function update() {
47394         var mapillary = getMapillary(),
47395             data = (mapillary ? mapillary.signs(projection) : []),
47396             imageKey = mapillary ? mapillary.selectedImage() : null;
47397
47398         var signs = layer.selectAll('.icon-sign')
47399             .data(data, function(d) { return d.key; });
47400
47401         signs.exit()
47402             .remove();
47403
47404         var enter = signs.enter()
47405             .append('foreignObject')
47406             .attr('class', 'icon-sign')
47407             .attr('width', '32px')      // for Firefox
47408             .attr('height', '32px')     // for Firefox
47409             .classed('selected', function(d) { return d.key === imageKey; })
47410             .on('click', click);
47411
47412         enter
47413             .append('xhtml:body')
47414             .attr('class', 'icon-sign-body')
47415             .html(mapillary.signHTML);
47416
47417         signs
47418             .merge(enter)
47419             .attr('x', function(d) { return projection(d.loc)[0] - 16; })   // offset by -16px to
47420             .attr('y', function(d) { return projection(d.loc)[1] - 16; });  // center signs on loc
47421     }
47422
47423
47424     function drawSigns(selection$$1) {
47425         var enabled = svgMapillarySigns.enabled,
47426             mapillary = getMapillary();
47427
47428         layer = selection$$1.selectAll('.layer-mapillary-signs')
47429             .data(mapillary ? [0] : []);
47430
47431         layer.exit()
47432             .remove();
47433
47434         layer = layer.enter()
47435             .append('g')
47436             .attr('class', 'layer-mapillary-signs')
47437             .style('display', enabled ? 'block' : 'none')
47438             .merge(layer);
47439
47440         if (enabled) {
47441             if (mapillary && ~~context.map().zoom() >= minZoom) {
47442                 editOn();
47443                 update();
47444                 mapillary.loadSigns(context, projection);
47445             } else {
47446                 editOff();
47447             }
47448         }
47449     }
47450
47451
47452     drawSigns.enabled = function(_) {
47453         if (!arguments.length) return svgMapillarySigns.enabled;
47454         svgMapillarySigns.enabled = _;
47455         if (svgMapillarySigns.enabled) {
47456             showLayer();
47457         } else {
47458             hideLayer();
47459         }
47460         dispatch$$1.call('change');
47461         return this;
47462     };
47463
47464
47465     drawSigns.supported = function() {
47466         var mapillary = getMapillary();
47467         return (mapillary && mapillary.signsSupported());
47468     };
47469
47470
47471     init();
47472     return drawSigns;
47473 }
47474
47475 function svgOsm() {
47476     return function drawOsm(selection) {
47477         var layers = selection.selectAll('.layer-osm')
47478             .data(['areas', 'lines', 'hit', 'halo', 'label']);
47479
47480         layers.enter()
47481             .append('g')
47482             .attr('class', function(d) { return 'layer-osm layer-' + d; });
47483     };
47484 }
47485
47486 function svgLayers(projection, context) {
47487     var dispatch$$1 = dispatch('change'),
47488         svg = select(null),
47489         layers = [
47490             { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
47491             { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
47492             { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
47493             { id: 'mapillary-signs',  layer: svgMapillarySigns(projection, context, dispatch$$1) },
47494             { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
47495         ];
47496
47497
47498     function drawLayers(selection$$1) {
47499         svg = selection$$1.selectAll('.surface')
47500             .data([0]);
47501
47502         svg = svg.enter()
47503             .append('svg')
47504             .attr('class', 'surface')
47505             .merge(svg);
47506
47507         var defs = svg.selectAll('.surface-defs')
47508             .data([0]);
47509
47510         defs.enter()
47511             .append('defs')
47512             .attr('class', 'surface-defs');
47513
47514         var groups = svg.selectAll('.data-layer')
47515             .data(layers);
47516
47517         groups.exit()
47518             .remove();
47519
47520         groups.enter()
47521             .append('g')
47522             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
47523             .merge(groups)
47524             .each(function(d) { select(this).call(d.layer); });
47525     }
47526
47527
47528     drawLayers.all = function() {
47529         return layers;
47530     };
47531
47532
47533     drawLayers.layer = function(id) {
47534         var obj = lodash.find(layers, function(o) {return o.id === id;});
47535         return obj && obj.layer;
47536     };
47537
47538
47539     drawLayers.only = function(what) {
47540         var arr = [].concat(what);
47541         drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
47542         return this;
47543     };
47544
47545
47546     drawLayers.remove = function(what) {
47547         var arr = [].concat(what);
47548         arr.forEach(function(id) {
47549             layers = lodash.reject(layers, function(o) {return o.id === id;});
47550         });
47551         dispatch$$1.call('change');
47552         return this;
47553     };
47554
47555
47556     drawLayers.add = function(what) {
47557         var arr = [].concat(what);
47558         arr.forEach(function(obj) {
47559             if ('id' in obj && 'layer' in obj) {
47560                 layers.push(obj);
47561             }
47562         });
47563         dispatch$$1.call('change');
47564         return this;
47565     };
47566
47567
47568     drawLayers.dimensions = function(_) {
47569         if (!arguments.length) return utilGetDimensions(svg);
47570         utilSetDimensions(svg, _);
47571         return this;
47572     };
47573
47574
47575     return utilRebind(drawLayers, dispatch$$1, 'on');
47576 }
47577
47578 function svgLines$$1(projection) {
47579     var detected = utilDetect();
47580
47581     var highway_stack = {
47582         motorway: 0,
47583         motorway_link: 1,
47584         trunk: 2,
47585         trunk_link: 3,
47586         primary: 4,
47587         primary_link: 5,
47588         secondary: 6,
47589         tertiary: 7,
47590         unclassified: 8,
47591         residential: 9,
47592         service: 10,
47593         footway: 11
47594     };
47595
47596     function waystack(a, b) {
47597         var as = 0, bs = 0;
47598         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
47599         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
47600         return as - bs;
47601     }
47602
47603
47604     return function drawLines(selection$$1, graph, entities, filter) {
47605         var ways = [], pathdata = {}, onewaydata = {},
47606             getPath = svgPath(projection, graph);
47607
47608         for (var i = 0; i < entities.length; i++) {
47609             var entity = entities[i],
47610                 outer = osmSimpleMultipolygonOuterMember(entity, graph);
47611             if (outer) {
47612                 ways.push(entity.mergeTags(outer.tags));
47613             } else if (entity.geometry(graph) === 'line') {
47614                 ways.push(entity);
47615             }
47616         }
47617
47618         ways = ways.filter(getPath);
47619
47620         pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
47621
47622         lodash.forOwn(pathdata, function(v, k) {
47623             onewaydata[k] = lodash(v)
47624                 .filter(function(d) { return d.isOneWay(); })
47625                 .map(svgOneWaySegments(projection, graph, 35))
47626                 .flatten()
47627                 .valueOf();
47628         });
47629
47630         var layer = selection$$1.selectAll('.layer-lines');
47631
47632         var layergroup = layer
47633             .selectAll('g.layergroup')
47634             .data(range(-10, 11));
47635
47636         layergroup = layergroup.enter()
47637             .append('g')
47638             .attr('class', function(d) { return 'layergroup layer' + String(d); })
47639             .merge(layergroup);
47640
47641
47642         var linegroup = layergroup
47643             .selectAll('g.linegroup')
47644             .data(['shadow', 'casing', 'stroke']);
47645
47646         linegroup = linegroup.enter()
47647             .append('g')
47648             .attr('class', function(d) { return 'linegroup line-' + d; })
47649             .merge(linegroup);
47650
47651
47652         var lines = linegroup
47653             .selectAll('path')
47654             .filter(filter)
47655             .data(
47656                 function() { return pathdata[this.parentNode.__data__] || []; },
47657                 osmEntity$$1.key
47658             );
47659
47660         lines.exit()
47661             .remove();
47662
47663         // Optimization: call simple TagClasses only on enter selection. This
47664         // works because osmEntity.key is defined to include the entity v attribute.
47665         lines.enter()
47666             .append('path')
47667             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
47668             .call(svgTagClasses())
47669             .merge(lines)
47670                 .sort(waystack)
47671                 .attr('d', getPath)
47672                 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
47673
47674
47675         var onewaygroup = layergroup
47676             .selectAll('g.onewaygroup')
47677             .data(['oneway']);
47678
47679         onewaygroup = onewaygroup.enter()
47680             .append('g')
47681             .attr('class', 'onewaygroup')
47682             .merge(onewaygroup);
47683
47684
47685         var oneways = onewaygroup
47686             .selectAll('path')
47687             .filter(filter)
47688             .data(
47689                 function() { return onewaydata[this.parentNode.__data__] || []; },
47690                 function(d) { return [d.id, d.index]; }
47691             );
47692
47693         oneways.exit()
47694             .remove();
47695
47696         oneways = oneways.enter()
47697             .append('path')
47698             .attr('class', 'oneway')
47699             .attr('marker-mid', 'url(#oneway-marker)')
47700             .merge(oneways)
47701             .attr('d', function(d) { return d.d; });
47702
47703         if (detected.ie) {
47704             oneways.each(function() { this.parentNode.insertBefore(this, this); });
47705         }
47706     };
47707 }
47708
47709 function svgMidpoints$$1(projection, context) {
47710
47711     return function drawMidpoints(selection, graph, entities, filter, extent) {
47712         var poly = extent.polygon(),
47713             midpoints = {};
47714
47715         for (var i = 0; i < entities.length; i++) {
47716             var entity = entities[i];
47717
47718             if (entity.type !== 'way')
47719                 continue;
47720             if (!filter(entity))
47721                 continue;
47722             if (context.selectedIDs().indexOf(entity.id) < 0)
47723                 continue;
47724
47725             var nodes = graph.childNodes(entity);
47726             for (var j = 0; j < nodes.length - 1; j++) {
47727
47728                 var a = nodes[j],
47729                     b = nodes[j + 1],
47730                     id = [a.id, b.id].sort().join('-');
47731
47732                 if (midpoints[id]) {
47733                     midpoints[id].parents.push(entity);
47734                 } else {
47735                     if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
47736                         var point = geoInterp(a.loc, b.loc, 0.5),
47737                             loc = null;
47738
47739                         if (extent.intersects(point)) {
47740                             loc = point;
47741                         } else {
47742                             for (var k = 0; k < 4; k++) {
47743                                 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
47744                                 if (point &&
47745                                     geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
47746                                     geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
47747                                 {
47748                                     loc = point;
47749                                     break;
47750                                 }
47751                             }
47752                         }
47753
47754                         if (loc) {
47755                             midpoints[id] = {
47756                                 type: 'midpoint',
47757                                 id: id,
47758                                 loc: loc,
47759                                 edge: [a.id, b.id],
47760                                 parents: [entity]
47761                             };
47762                         }
47763                     }
47764                 }
47765             }
47766         }
47767
47768
47769         function midpointFilter(d) {
47770             if (midpoints[d.id])
47771                 return true;
47772
47773             for (var i = 0; i < d.parents.length; i++) {
47774                 if (filter(d.parents[i])) {
47775                     return true;
47776                 }
47777             }
47778
47779             return false;
47780         }
47781
47782
47783         var layer = selection.selectAll('.layer-hit');
47784
47785         var groups = layer
47786             .selectAll('g.midpoint')
47787             .filter(midpointFilter)
47788             .data(lodash.values(midpoints), function(d) { return d.id; });
47789
47790         groups.exit()
47791             .remove();
47792
47793         var enter = groups.enter()
47794             .insert('g', ':first-child')
47795             .attr('class', 'midpoint');
47796
47797         enter.append('polygon')
47798             .attr('points', '-6,8 10,0 -6,-8')
47799             .attr('class', 'shadow');
47800
47801         enter.append('polygon')
47802             .attr('points', '-3,4 5,0 -3,-4')
47803             .attr('class', 'fill');
47804
47805         groups = groups
47806             .merge(enter)
47807             .attr('transform', function(d) {
47808                 var translate = svgPointTransform(projection),
47809                     a = graph.entity(d.edge[0]),
47810                     b = graph.entity(d.edge[1]),
47811                     angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
47812                 return translate(d) + ' rotate(' + angleVal + ')';
47813             })
47814             .call(svgTagClasses().tags(
47815                 function(d) { return d.parents[0].tags; }
47816             ));
47817
47818         // Propagate data bindings.
47819         groups.select('polygon.shadow');
47820         groups.select('polygon.fill');
47821
47822     };
47823 }
47824
47825 function svgOneWaySegments(projection, graph, dt) {
47826     return function(entity) {
47827         var a,
47828             b,
47829             i = 0,
47830             offset = dt,
47831             segments = [],
47832             clip = identity$8().clipExtent(projection.clipExtent()).stream,
47833             coordinates = graph.childNodes(entity).map(function(n) {
47834                 return n.loc;
47835             });
47836
47837         if (entity.tags.oneway === '-1') coordinates.reverse();
47838
47839         geoStream({
47840             type: 'LineString',
47841             coordinates: coordinates
47842         }, projection.stream(clip({
47843             lineStart: function() {},
47844             lineEnd: function() {
47845                 a = null;
47846             },
47847             point: function(x, y) {
47848                 b = [x, y];
47849
47850                 if (a) {
47851                     var span = geoEuclideanDistance(a, b) - offset;
47852
47853                     if (span >= 0) {
47854                         var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
47855                             dx = dt * Math.cos(angle),
47856                             dy = dt * Math.sin(angle),
47857                             p = [a[0] + offset * Math.cos(angle),
47858                                  a[1] + offset * Math.sin(angle)];
47859
47860                         var segment = 'M' + a[0] + ',' + a[1] +
47861                                       'L' + p[0] + ',' + p[1];
47862
47863                         for (span -= dt; span >= 0; span -= dt) {
47864                             p[0] += dx;
47865                             p[1] += dy;
47866                             segment += 'L' + p[0] + ',' + p[1];
47867                         }
47868
47869                         segment += 'L' + b[0] + ',' + b[1];
47870                         segments.push({id: entity.id, index: i, d: segment});
47871                     }
47872
47873                     offset = -span;
47874                     i++;
47875                 }
47876
47877                 a = b;
47878             }
47879         })));
47880
47881         return segments;
47882     };
47883 }
47884
47885 function svgPath(projection, graph, isArea) {
47886
47887     // Explanation of magic numbers:
47888     // "padding" here allows space for strokes to extend beyond the viewport,
47889     // so that the stroke isn't drawn along the edge of the viewport when
47890     // the shape is clipped.
47891     //
47892     // When drawing lines, pad viewport by 5px.
47893     // When drawing areas, pad viewport by 65px in each direction to allow
47894     // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
47895
47896     var cache = {},
47897         padding = isArea ? 65 : 5,
47898         viewport = projection.clipExtent(),
47899         paddedExtent = [
47900             [viewport[0][0] - padding, viewport[0][1] - padding],
47901             [viewport[1][0] + padding, viewport[1][1] + padding]
47902         ],
47903         clip = identity$8().clipExtent(paddedExtent).stream,
47904         project = projection.stream,
47905         path$$1 = index$5()
47906             .projection({stream: function(output) { return project(clip(output)); }});
47907
47908     return function(entity) {
47909         if (entity.id in cache) {
47910             return cache[entity.id];
47911         } else {
47912             return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
47913         }
47914     };
47915 }
47916
47917 function svgPoints$$1(projection, context) {
47918
47919     function markerPath(selection, klass) {
47920         selection
47921             .attr('class', klass)
47922             .attr('transform', 'translate(-8, -23)')
47923             .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');
47924     }
47925
47926     function sortY(a, b) {
47927         return b.loc[1] - a.loc[1];
47928     }
47929
47930
47931     return function drawPoints(selection, graph, entities, filter) {
47932         var wireframe = context.surface().classed('fill-wireframe'),
47933             points = wireframe ? [] : lodash.filter(entities, function(e) {
47934                 return e.geometry(graph) === 'point';
47935             });
47936
47937         points.sort(sortY);
47938
47939         var layer = selection.selectAll('.layer-hit');
47940
47941         var groups = layer.selectAll('g.point')
47942             .filter(filter)
47943             .data(points, osmEntity$$1.key);
47944
47945         groups.exit()
47946             .remove();
47947
47948         var enter = groups.enter()
47949             .append('g')
47950             .attr('class', function(d) { return 'node point ' + d.id; })
47951             .order();
47952
47953         enter.append('path')
47954             .call(markerPath, 'shadow');
47955
47956         enter.append('path')
47957             .call(markerPath, 'stroke');
47958
47959         enter.append('use')
47960             .attr('transform', 'translate(-6, -20)')
47961             .attr('class', 'icon')
47962             .attr('width', '12px')
47963             .attr('height', '12px');
47964
47965         groups = groups
47966             .merge(enter)
47967             .attr('transform', svgPointTransform(projection))
47968             .call(svgTagClasses());
47969
47970         // Selecting the following implicitly
47971         // sets the data (point entity) on the element
47972         groups.select('.shadow');
47973         groups.select('.stroke');
47974         groups.select('.icon')
47975             .attr('xlink:href', function(entity) {
47976                 var preset = context.presets().match(entity, graph);
47977                 return (preset && preset.icon) ? '#' + preset.icon + '-12' : '';
47978             });
47979     };
47980 }
47981
47982 function svgRelationMemberTags(graph) {
47983     return function(entity) {
47984         var tags = entity.tags;
47985         graph.parentRelations(entity).forEach(function(relation) {
47986             var type = relation.tags.type;
47987             if (type === 'multipolygon' || type === 'boundary') {
47988                 tags = lodash.extend({}, relation.tags, tags);
47989             }
47990         });
47991         return tags;
47992     };
47993 }
47994
47995 function svgTagClasses() {
47996     var primaries = [
47997             'building', 'highway', 'railway', 'waterway', 'aeroway',
47998             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
47999             'leisure', 'place'
48000         ],
48001         statuses = [
48002             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
48003             'razed', 'demolished', 'obliterated'
48004         ],
48005         secondaries = [
48006             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
48007             'surface', 'tracktype', 'crossing'
48008         ],
48009         tagClassRe = /^tag-/,
48010         tags = function(entity) { return entity.tags; };
48011
48012
48013     var tagClasses = function(selection$$1) {
48014         selection$$1.each(function tagClassesEach(entity) {
48015             var value = this.className,
48016                 classes, primary, status;
48017
48018             if (value.baseVal !== undefined) value = value.baseVal;
48019
48020             classes = value.trim().split(/\s+/).filter(function(name) {
48021                 return name.length && !tagClassRe.test(name);
48022             }).join(' ');
48023
48024             var t = tags(entity), i, k, v;
48025
48026             // pick at most one primary classification tag..
48027             for (i = 0; i < primaries.length; i++) {
48028                 k = primaries[i];
48029                 v = t[k];
48030                 if (!v || v === 'no') continue;
48031
48032                 primary = k;
48033                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
48034                     status = v;
48035                     classes += ' tag-' + k;
48036                 } else {
48037                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
48038                 }
48039
48040                 break;
48041             }
48042
48043             // add at most one status tag, only if relates to primary tag..
48044             if (!status) {
48045                 for (i = 0; i < statuses.length; i++) {
48046                     k = statuses[i];
48047                     v = t[k];
48048                     if (!v || v === 'no') continue;
48049
48050                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
48051                         status = k;
48052                     }
48053                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
48054                         status = k;
48055                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
48056                         status = k;
48057                         primary = v;
48058                         classes += ' tag-' + v;
48059                     }  // else ignore e.g.  `highway=path + abandoned=railway`
48060
48061                     if (status) break;
48062                 }
48063             }
48064
48065             if (status) {
48066                 classes += ' tag-status tag-status-' + status;
48067             }
48068
48069             // add any secondary (structure) tags
48070             for (i = 0; i < secondaries.length; i++) {
48071                 k = secondaries[i];
48072                 v = t[k];
48073                 if (!v || v === 'no') continue;
48074                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48075             }
48076
48077             // For highways, look for surface tagging..
48078             if (primary === 'highway') {
48079                 var paved = (t.highway !== 'track');
48080                 for (k in t) {
48081                     v = t[k];
48082                     if (k in osmPavedTags) {
48083                         paved = !!osmPavedTags[k][v];
48084                         break;
48085                     }
48086                 }
48087                 if (!paved) {
48088                     classes += ' tag-unpaved';
48089                 }
48090             }
48091
48092             classes = classes.trim();
48093
48094             if (classes !== value) {
48095                 select(this).attr('class', classes);
48096             }
48097         });
48098     };
48099
48100
48101     tagClasses.tags = function(_) {
48102         if (!arguments.length) return tags;
48103         tags = _;
48104         return tagClasses;
48105     };
48106
48107     return tagClasses;
48108 }
48109
48110 function svgTurns(projection) {
48111
48112     return function drawTurns(selection, graph, turns) {
48113
48114         function key(turn) {
48115             return [turn.from.node + turn.via.node + turn.to.node].join('-');
48116         }
48117
48118         function icon(turn) {
48119             var u = turn.u ? '-u' : '';
48120             if (!turn.restriction)
48121                 return '#turn-yes' + u;
48122             var restriction = graph.entity(turn.restriction).tags.restriction;
48123             return '#turn-' +
48124                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48125         }
48126
48127         var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48128             .data(turns, key);
48129
48130         groups.exit()
48131             .remove();
48132
48133
48134         var enter = groups.enter()
48135             .append('g')
48136             .attr('class', 'turn');
48137
48138         var nEnter = enter
48139             .filter(function (turn) { return !turn.u; });
48140
48141         nEnter.append('rect')
48142             .attr('transform', 'translate(-22, -12)')
48143             .attr('width', '44')
48144             .attr('height', '24');
48145
48146         nEnter.append('use')
48147             .attr('transform', 'translate(-22, -12)')
48148             .attr('width', '44')
48149             .attr('height', '24');
48150
48151
48152         var uEnter = enter
48153             .filter(function (turn) { return turn.u; });
48154
48155         uEnter.append('circle')
48156             .attr('r', '16');
48157
48158         uEnter.append('use')
48159             .attr('transform', 'translate(-16, -16)')
48160             .attr('width', '32')
48161             .attr('height', '32');
48162
48163
48164         groups = groups
48165             .merge(enter);
48166
48167         groups
48168             .attr('transform', function (turn) {
48169                 var v = graph.entity(turn.via.node),
48170                     t = graph.entity(turn.to.node),
48171                     a = geoAngle(v, t, projection),
48172                     p = projection(v.loc),
48173                     r = turn.u ? 0 : 60;
48174
48175                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
48176                     'rotate(' + a * 180 / Math.PI + ')';
48177             });
48178
48179         groups.select('use')
48180             .attr('xlink:href', icon);
48181
48182         groups.select('rect');
48183         groups.select('circle');
48184
48185         return this;
48186     };
48187 }
48188
48189 function svgVertices$$1(projection, context) {
48190     var radiuses = {
48191         //       z16-, z17, z18+, tagged
48192         shadow: [6,    7.5,   7.5,  11.5],
48193         stroke: [2.5,  3.5,   3.5,  7],
48194         fill:   [1,    1.5,   1.5,  1.5]
48195     };
48196
48197     var hover;
48198
48199     function siblingAndChildVertices(ids, graph, extent$$1) {
48200         var vertices = {};
48201
48202         function addChildVertices(entity) {
48203             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
48204                 var i;
48205                 if (entity.type === 'way') {
48206                     for (i = 0; i < entity.nodes.length; i++) {
48207                         addChildVertices(graph.entity(entity.nodes[i]));
48208                     }
48209                 } else if (entity.type === 'relation') {
48210                     for (i = 0; i < entity.members.length; i++) {
48211                         var member = context.hasEntity(entity.members[i].id);
48212                         if (member) {
48213                             addChildVertices(member);
48214                         }
48215                     }
48216                 } else if (entity.intersects(extent$$1, graph)) {
48217                     vertices[entity.id] = entity;
48218                 }
48219             }
48220         }
48221
48222         ids.forEach(function(id) {
48223             var entity = context.hasEntity(id);
48224             if (entity && entity.type === 'node') {
48225                 vertices[entity.id] = entity;
48226                 context.graph().parentWays(entity).forEach(function(entity) {
48227                     addChildVertices(entity);
48228                 });
48229             } else if (entity) {
48230                 addChildVertices(entity);
48231             }
48232         });
48233
48234         return vertices;
48235     }
48236
48237
48238     function draw(selection$$1, vertices, klass, graph, zoom$$1) {
48239
48240         function icon(entity) {
48241             if (entity.id in icons) return icons[entity.id];
48242             icons[entity.id] =
48243                 entity.hasInterestingTags() &&
48244                 context.presets().match(entity, graph).icon;
48245             return icons[entity.id];
48246         }
48247
48248         function setClass(klass) {
48249             return function(entity) {
48250                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
48251             };
48252         }
48253
48254         function setAttributes(selection$$1) {
48255             ['shadow','stroke','fill'].forEach(function(klass) {
48256                 var rads = radiuses[klass];
48257                 selection$$1.selectAll('.' + klass)
48258                     .each(function(entity) {
48259                         var i = z && icon(entity),
48260                             c = i ? 0.5 : 0,
48261                             r = rads[i ? 3 : z];
48262                         this.setAttribute('cx', c);
48263                         this.setAttribute('cy', -c);
48264                         this.setAttribute('r', r);
48265                         if (i && klass === 'fill') {
48266                             this.setAttribute('visibility', 'hidden');
48267                         } else {
48268                             this.removeAttribute('visibility');
48269                         }
48270                     });
48271             });
48272
48273             selection$$1.selectAll('use')
48274                 .each(function() {
48275                     if (z) {
48276                         this.removeAttribute('visibility');
48277                     } else {
48278                         this.setAttribute('visibility', 'hidden');
48279                     }
48280                 });
48281         }
48282
48283
48284         var icons = {},
48285             z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
48286
48287         var groups = selection$$1
48288             .data(vertices, osmEntity$$1.key);
48289
48290         groups.exit()
48291             .remove();
48292
48293         var enter = groups.enter()
48294             .append('g')
48295             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
48296
48297         enter.append('circle')
48298             .each(setClass('shadow'));
48299
48300         enter.append('circle')
48301             .each(setClass('stroke'));
48302
48303         // Vertices with icons get a `use`.
48304         enter.filter(function(d) { return icon(d); })
48305             .append('use')
48306             .attr('transform', 'translate(-6, -6)')
48307             .attr('xlink:href', function(d) { return '#' + icon(d) + '-12'; })
48308             .attr('width', '12px')
48309             .attr('height', '12px')
48310             .each(setClass('icon'));
48311
48312         // Vertices with tags get a fill.
48313         enter.filter(function(d) { return d.hasInterestingTags(); })
48314             .append('circle')
48315             .each(setClass('fill'));
48316
48317         groups
48318             .merge(enter)
48319             .attr('transform', svgPointTransform(projection))
48320             .classed('shared', function(entity) { return graph.isShared(entity); })
48321             .call(setAttributes);
48322     }
48323
48324
48325     function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
48326         var selected = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
48327             wireframe = context.surface().classed('fill-wireframe'),
48328             vertices = [];
48329
48330         for (var i = 0; i < entities.length; i++) {
48331             var entity = entities[i],
48332                 geometry = entity.geometry(graph);
48333
48334             if (wireframe && geometry === 'point') {
48335                 vertices.push(entity);
48336                 continue;
48337             }
48338
48339             if (geometry !== 'vertex')
48340                 continue;
48341
48342             if (entity.id in selected ||
48343                 entity.hasInterestingTags() ||
48344                 entity.isIntersection(graph)) {
48345                 vertices.push(entity);
48346             }
48347         }
48348
48349         var layer = selection$$1.selectAll('.layer-hit');
48350         layer.selectAll('g.vertex.vertex-persistent')
48351             .filter(filter)
48352             .call(draw, vertices, 'vertex-persistent', graph, zoom$$1);
48353
48354         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48355     }
48356
48357
48358     function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
48359         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
48360         var layer = selection$$1.selectAll('.layer-hit');
48361
48362         layer.selectAll('g.vertex.vertex-hover')
48363             .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
48364     }
48365
48366
48367     drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
48368         if (target === hover) return;
48369         hover = target;
48370         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48371     };
48372
48373     return drawVertices;
48374 }
48375
48376 function behaviorEdit(context) {
48377
48378     function edit() {
48379         context.map()
48380             .minzoom(context.minEditableZoom());
48381     }
48382
48383
48384     edit.off = function() {
48385         context.map()
48386             .minzoom(0);
48387     };
48388
48389
48390     return edit;
48391 }
48392
48393 /*
48394    The hover behavior adds the `.hover` class on mouseover to all elements to which
48395    the identical datum is bound, and removes it on mouseout.
48396
48397    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
48398    representation may consist of several elements scattered throughout the DOM hierarchy.
48399    Only one of these elements can have the :hover pseudo-class, but all of them will
48400    have the .hover class.
48401  */
48402 function behaviorHover() {
48403     var dispatch$$1 = dispatch('hover'),
48404         selection$$1 = select(null),
48405         buttonDown,
48406         altDisables,
48407         target;
48408
48409
48410     function keydown() {
48411         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48412             dispatch$$1.call('hover', this, null);
48413             selection$$1.selectAll('.hover')
48414                 .classed('hover-suppressed', true)
48415                 .classed('hover', false);
48416         }
48417     }
48418
48419
48420     function keyup() {
48421         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48422             dispatch$$1.call('hover', this, target ? target.id : null);
48423             selection$$1.selectAll('.hover-suppressed')
48424                 .classed('hover-suppressed', false)
48425                 .classed('hover', true);
48426         }
48427     }
48428
48429
48430     var hover = function(__) {
48431         selection$$1 = __;
48432
48433         selection$$1
48434             .on('mouseover.hover', mouseover)
48435             .on('mouseout.hover', mouseout)
48436             .on('mousedown.hover', mousedown);
48437
48438         select(window)
48439             .on('keydown.hover', keydown)
48440             .on('keyup.hover', keyup);
48441
48442
48443         function mouseover() {
48444             if (buttonDown) return;
48445             var target = event.target;
48446             enter(target ? target.__data__ : null);
48447         }
48448
48449
48450         function mouseout() {
48451             if (buttonDown) return;
48452             var target = event.relatedTarget;
48453             enter(target ? target.__data__ : null);
48454         }
48455
48456
48457         function mousedown() {
48458             buttonDown = true;
48459             select(window)
48460                 .on('mouseup.hover', mouseup, true);
48461         }
48462
48463
48464         function mouseup() {
48465             buttonDown = false;
48466             select(window)
48467                 .on('mouseup.hover', null, true);
48468         }
48469
48470
48471         function enter(d) {
48472             if (d === target) return;
48473             target = d;
48474
48475             selection$$1.selectAll('.hover')
48476                 .classed('hover', false);
48477             selection$$1.selectAll('.hover-suppressed')
48478                 .classed('hover-suppressed', false);
48479
48480             if (target instanceof osmEntity$$1) {
48481                 var selector$$1 = '.' + target.id;
48482
48483                 if (target.type === 'relation') {
48484                     target.members.forEach(function(member) {
48485                         selector$$1 += ', .' + member.id;
48486                     });
48487                 }
48488
48489                 var suppressed = altDisables && event && event.altKey;
48490
48491                 selection$$1.selectAll(selector$$1)
48492                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
48493
48494                 dispatch$$1.call('hover', this, target.id);
48495             } else {
48496                 dispatch$$1.call('hover', this, null);
48497             }
48498         }
48499
48500     };
48501
48502
48503     hover.off = function(selection$$1) {
48504         selection$$1.selectAll('.hover')
48505             .classed('hover', false);
48506         selection$$1.selectAll('.hover-suppressed')
48507             .classed('hover-suppressed', false);
48508
48509         selection$$1
48510             .on('mouseover.hover', null)
48511             .on('mouseout.hover', null)
48512             .on('mousedown.hover', null);
48513
48514         select(window)
48515             .on('keydown.hover', null)
48516             .on('keyup.hover', null);
48517     };
48518
48519
48520     hover.altDisables = function(_) {
48521         if (!arguments.length) return altDisables;
48522         altDisables = _;
48523         return hover;
48524     };
48525
48526
48527     return utilRebind(hover, dispatch$$1, 'on');
48528 }
48529
48530 function behaviorTail() {
48531     var text$$1,
48532         container,
48533         xmargin = 25,
48534         tooltipSize = [0, 0],
48535         selectionSize = [0, 0];
48536
48537
48538     function tail(selection$$1) {
48539         if (!text$$1) return;
48540
48541         select(window)
48542             .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
48543
48544         container = select(document.body)
48545             .append('div')
48546             .style('display', 'none')
48547             .attr('class', 'tail tooltip-inner');
48548
48549         container.append('div')
48550             .text(text$$1);
48551
48552         selection$$1
48553             .on('mousemove.tail', mousemove)
48554             .on('mouseenter.tail', mouseenter)
48555             .on('mouseleave.tail', mouseleave);
48556
48557         container
48558             .on('mousemove.tail', mousemove);
48559
48560         tooltipSize = utilGetDimensions(container);
48561         selectionSize = utilGetDimensions(selection$$1);
48562
48563
48564         function show() {
48565             container.style('display', 'block');
48566             tooltipSize = utilGetDimensions(container);
48567         }
48568
48569
48570         function mousemove() {
48571             if (container.style('display') === 'none') show();
48572             var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
48573                 -tooltipSize[0] - xmargin : xmargin;
48574             container.classed('left', xoffset > 0);
48575             utilSetTransform(container, event.clientX + xoffset, event.clientY);
48576         }
48577
48578
48579         function mouseleave() {
48580             if (event.relatedTarget !== container.node()) {
48581                 container.style('display', 'none');
48582             }
48583         }
48584
48585
48586         function mouseenter() {
48587             if (event.relatedTarget !== container.node()) {
48588                 show();
48589             }
48590         }
48591     }
48592
48593
48594     tail.off = function(selection$$1) {
48595         if (!text$$1) return;
48596
48597         container
48598             .on('mousemove.tail', null)
48599             .remove();
48600
48601         selection$$1
48602             .on('mousemove.tail', null)
48603             .on('mouseenter.tail', null)
48604             .on('mouseleave.tail', null);
48605
48606         select(window)
48607             .on('resize.tail', null);
48608     };
48609
48610
48611     tail.text = function(_) {
48612         if (!arguments.length) return text$$1;
48613         text$$1 = _;
48614         return tail;
48615     };
48616
48617
48618     return tail;
48619 }
48620
48621 behaviorDraw.usedTails = {};
48622 behaviorDraw.disableSpace = false;
48623 behaviorDraw.lastSpace = null;
48624
48625
48626 function behaviorDraw(context) {
48627     var dispatch$$1 = dispatch('move', 'click', 'clickWay',
48628             'clickNode', 'undo', 'cancel', 'finish'),
48629         keybinding = d3keybinding('draw'),
48630         hover = behaviorHover(context)
48631             .altDisables(true)
48632             .on('hover', context.ui().sidebar.hover),
48633         tail = behaviorTail(),
48634         edit = behaviorEdit(context),
48635         closeTolerance = 4,
48636         tolerance = 12,
48637         mouseLeave = false,
48638         lastMouse = null,
48639         cached = behaviorDraw;
48640
48641
48642     function datum() {
48643         if (event.altKey) return {};
48644
48645         if (event.type === 'keydown') {
48646             return (lastMouse && lastMouse.target.__data__) || {};
48647         } else {
48648             return event.target.__data__ || {};
48649         }
48650     }
48651
48652
48653     function mousedown() {
48654
48655         function point() {
48656             var p = context.container().node();
48657             return touchId !== null ? touches(p).filter(function(p) {
48658                 return p.identifier === touchId;
48659             })[0] : mouse(p);
48660         }
48661
48662         var element = select(this),
48663             touchId = event.touches ? event.changedTouches[0].identifier : null,
48664             t1 = +new Date(),
48665             p1 = point();
48666
48667         element.on('mousemove.draw', null);
48668
48669         select(window).on('mouseup.draw', function() {
48670             var t2 = +new Date(),
48671                 p2 = point(),
48672                 dist = geoEuclideanDistance(p1, p2);
48673
48674             element.on('mousemove.draw', mousemove);
48675             select(window).on('mouseup.draw', null);
48676
48677             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
48678                 // Prevent a quick second click
48679                 select(window).on('click.draw-block', function() {
48680                     event.stopPropagation();
48681                 }, true);
48682
48683                 context.map().dblclickEnable(false);
48684
48685                 window.setTimeout(function() {
48686                     context.map().dblclickEnable(true);
48687                     select(window).on('click.draw-block', null);
48688                 }, 500);
48689
48690                 click();
48691             }
48692         }, true);
48693     }
48694
48695
48696     function mousemove() {
48697         lastMouse = event;
48698         dispatch$$1.call('move', this, datum());
48699     }
48700
48701
48702     function mouseenter() {
48703         mouseLeave = false;
48704     }
48705
48706
48707     function mouseleave() {
48708         mouseLeave = true;
48709     }
48710
48711
48712     function click() {
48713         var d = datum();
48714         if (d.type === 'way') {
48715             var dims = context.map().dimensions(),
48716                 mouse$$1 = context.mouse(),
48717                 pad = 5,
48718                 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
48719                     mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
48720
48721             if (trySnap) {
48722                 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
48723                     edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
48724                 dispatch$$1.call('clickWay', this, choice.loc, edge);
48725             } else {
48726                 dispatch$$1.call('click', this, context.map().mouseCoordinates());
48727             }
48728
48729         } else if (d.type === 'node') {
48730             dispatch$$1.call('clickNode', this, d);
48731
48732         } else {
48733             dispatch$$1.call('click', this, context.map().mouseCoordinates());
48734         }
48735     }
48736
48737
48738     function space() {
48739         var currSpace = context.mouse();
48740         if (cached.disableSpace && cached.lastSpace) {
48741             var dist = geoEuclideanDistance(cached.lastSpace, currSpace);
48742             if (dist > tolerance) {
48743                 cached.disableSpace = false;
48744             }
48745         }
48746
48747         if (cached.disableSpace || mouseLeave || !lastMouse) return;
48748
48749         // user must move mouse or release space bar to allow another click
48750         cached.lastSpace = currSpace;
48751         cached.disableSpace = true;
48752
48753         select(window).on('keyup.space-block', function() {
48754             cached.disableSpace = false;
48755             select(window).on('keyup.space-block', null);
48756         });
48757
48758         event.preventDefault();
48759         click();
48760     }
48761
48762
48763     function backspace() {
48764         event.preventDefault();
48765         dispatch$$1.call('undo');
48766     }
48767
48768
48769     function del() {
48770         event.preventDefault();
48771         dispatch$$1.call('cancel');
48772     }
48773
48774
48775     function ret() {
48776         event.preventDefault();
48777         dispatch$$1.call('finish');
48778     }
48779
48780
48781     function draw(selection$$1) {
48782         context.install(hover);
48783         context.install(edit);
48784
48785         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
48786             context.install(tail);
48787         }
48788
48789         keybinding
48790             .on('⌫', backspace)
48791             .on('⌦', del)
48792             .on('⎋', ret)
48793             .on('↩', ret)
48794             .on('space', space)
48795             .on('⌥space', space);
48796
48797         selection$$1
48798             .on('mouseenter.draw', mouseenter)
48799             .on('mouseleave.draw', mouseleave)
48800             .on('mousedown.draw', mousedown)
48801             .on('mousemove.draw', mousemove);
48802
48803         select(document)
48804             .call(keybinding);
48805
48806         return draw;
48807     }
48808
48809
48810     draw.off = function(selection$$1) {
48811         context.ui().sidebar.hover.cancel();
48812         context.uninstall(hover);
48813         context.uninstall(edit);
48814
48815         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
48816             context.uninstall(tail);
48817             cached.usedTails[tail.text()] = true;
48818         }
48819
48820         selection$$1
48821             .on('mouseenter.draw', null)
48822             .on('mouseleave.draw', null)
48823             .on('mousedown.draw', null)
48824             .on('mousemove.draw', null);
48825
48826         select(window)
48827             .on('mouseup.draw', null);
48828             // note: keyup.space-block, click.draw-block should remain
48829
48830         select(document)
48831             .call(keybinding.off);
48832     };
48833
48834
48835     draw.tail = function(_) {
48836         tail.text(_);
48837         return draw;
48838     };
48839
48840
48841     return utilRebind(draw, dispatch$$1, 'on');
48842 }
48843
48844 function behaviorAddWay(context) {
48845     var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
48846         draw = behaviorDraw(context);
48847
48848     var addWay = function(surface) {
48849         draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
48850             .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
48851             .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
48852             .on('cancel', addWay.cancel)
48853             .on('finish', addWay.cancel);
48854
48855         context.map()
48856             .dblclickEnable(false);
48857
48858         surface.call(draw);
48859     };
48860
48861
48862     addWay.off = function(surface) {
48863         surface.call(draw.off);
48864     };
48865
48866
48867     addWay.cancel = function() {
48868         window.setTimeout(function() {
48869             context.map().dblclickEnable(true);
48870         }, 1000);
48871
48872         context.enter(modeBrowse$$1(context));
48873     };
48874
48875
48876     addWay.tail = function(text$$1) {
48877         draw.tail(text$$1);
48878         return addWay;
48879     };
48880
48881
48882     return utilRebind(addWay, dispatch$$1, 'on');
48883 }
48884
48885 function behaviorBreathe() {
48886     var duration = 800,
48887         steps = 4,
48888         selector$$1 = '.selected.shadow, .selected .shadow',
48889         selected = select(null),
48890         classed = '',
48891         params = {},
48892         done = false,
48893         timer$$1;
48894
48895
48896     // This is a workaround for a bug in rollup v0.36
48897     // https://github.com/rollup/rollup/issues/984
48898     // The symbol for this default export is not used anywhere, but it
48899     // needs to be called in order to be included in the bundle.
48900     var t = transition();
48901
48902
48903     function ratchetyInterpolator(a, b, steps, units) {
48904         a = parseFloat(a);
48905         b = parseFloat(b);
48906         var sample = quantize$1()
48907             .domain([0, 1])
48908             .range(quantize(interpolateNumber(a, b), steps));
48909
48910         return function(t) {
48911             return String(sample(t)) + (units || '');
48912         };
48913     }
48914
48915
48916     function reset(selection$$1) {
48917         selection$$1
48918             .style('stroke-opacity', null)
48919             .style('stroke-width', null)
48920             .style('fill-opacity', null)
48921             .style('r', null);
48922     }
48923
48924
48925     function setAnimationParams(transition$$1, fromTo) {
48926         var toFrom = (fromTo === 'from' ? 'to' : 'from');
48927
48928         transition$$1
48929             .styleTween('stroke-opacity', function(d) {
48930                 return ratchetyInterpolator(
48931                     params[d.id][toFrom].opacity,
48932                     params[d.id][fromTo].opacity,
48933                     steps
48934                 );
48935             })
48936             .styleTween('stroke-width', function(d) {
48937                 return ratchetyInterpolator(
48938                     params[d.id][toFrom].width,
48939                     params[d.id][fromTo].width,
48940                     steps,
48941                     'px'
48942                 );
48943             })
48944             .styleTween('fill-opacity', function(d) {
48945                 return ratchetyInterpolator(
48946                     params[d.id][toFrom].opacity,
48947                     params[d.id][fromTo].opacity,
48948                     steps
48949                 );
48950             })
48951             .styleTween('r', function(d) {
48952                 return ratchetyInterpolator(
48953                     params[d.id][toFrom].width,
48954                     params[d.id][fromTo].width,
48955                     steps,
48956                     'px'
48957                 );
48958             });
48959     }
48960
48961
48962     function calcAnimationParams(selection$$1) {
48963         selection$$1
48964             .call(reset)
48965             .each(function(d) {
48966                 var s = select(this),
48967                     tag = s.node().tagName,
48968                     p = {'from': {}, 'to': {}},
48969                     opacity, width;
48970
48971                 // determine base opacity and width
48972                 if (tag === 'circle') {
48973                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
48974                     width = parseFloat(s.style('r') || 15.5);
48975                 } else {
48976                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
48977                     width = parseFloat(s.style('stroke-width') || 10);
48978                 }
48979
48980                 // calculate from/to interpolation params..
48981                 p.tag = tag;
48982                 p.from.opacity = opacity * 0.6;
48983                 p.to.opacity = opacity * 1.25;
48984                 p.from.width = width * 0.9;
48985                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
48986                 params[d.id] = p;
48987             });
48988     }
48989
48990
48991     function run(surface, fromTo) {
48992         var toFrom = (fromTo === 'from' ? 'to' : 'from'),
48993             currSelected = surface.selectAll(selector$$1),
48994             currClassed = surface.attr('class');
48995
48996         if (done || currSelected.empty()) {
48997             selected.call(reset);
48998             return;
48999         }
49000
49001         if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
49002             selected.call(reset);
49003             classed = currClassed;
49004             selected = currSelected.call(calcAnimationParams);
49005         }
49006
49007         selected
49008             .transition()
49009             .duration(duration)
49010             .call(setAnimationParams, fromTo)
49011             .on('end', function() {
49012                 surface.call(run, toFrom);
49013             });
49014     }
49015
49016
49017     var breathe = function(surface) {
49018         done = false;
49019         timer$$1 = timer(function() {
49020             // wait for elements to actually become selected
49021             if (surface.selectAll(selector$$1).empty()) {
49022                 return false;
49023             }
49024
49025             surface.call(run, 'from');
49026             timer$$1.stop();
49027             return true;
49028         }, 20);
49029     };
49030
49031
49032     breathe.off = function() {
49033         done = true;
49034         timer$$1.stop();
49035         selected
49036             .interrupt()
49037             .call(reset);
49038     };
49039
49040
49041     return breathe;
49042 }
49043
49044 function behaviorCopy(context) {
49045     var keybinding = d3keybinding('copy');
49046
49047
49048     function groupEntities(ids, graph) {
49049         var entities = ids.map(function (id) { return graph.entity(id); });
49050         return lodash.extend({relation: [], way: [], node: []},
49051             lodash.groupBy(entities, function(entity) { return entity.type; }));
49052     }
49053
49054
49055     function getDescendants(id, graph, descendants) {
49056         var entity = graph.entity(id),
49057             i, children;
49058
49059         descendants = descendants || {};
49060
49061         if (entity.type === 'relation') {
49062             children = lodash.map(entity.members, 'id');
49063         } else if (entity.type === 'way') {
49064             children = entity.nodes;
49065         } else {
49066             children = [];
49067         }
49068
49069         for (i = 0; i < children.length; i++) {
49070             if (!descendants[children[i]]) {
49071                 descendants[children[i]] = true;
49072                 descendants = getDescendants(children[i], graph, descendants);
49073             }
49074         }
49075
49076         return descendants;
49077     }
49078
49079
49080     function doCopy() {
49081         event.preventDefault();
49082         if (context.inIntro()) return;
49083
49084         var graph = context.graph(),
49085             selected = groupEntities(context.selectedIDs(), graph),
49086             canCopy = [],
49087             skip = {},
49088             i, entity;
49089
49090         for (i = 0; i < selected.relation.length; i++) {
49091             entity = selected.relation[i];
49092             if (!skip[entity.id] && entity.isComplete(graph)) {
49093                 canCopy.push(entity.id);
49094                 skip = getDescendants(entity.id, graph, skip);
49095             }
49096         }
49097         for (i = 0; i < selected.way.length; i++) {
49098             entity = selected.way[i];
49099             if (!skip[entity.id]) {
49100                 canCopy.push(entity.id);
49101                 skip = getDescendants(entity.id, graph, skip);
49102             }
49103         }
49104         for (i = 0; i < selected.node.length; i++) {
49105             entity = selected.node[i];
49106             if (!skip[entity.id]) {
49107                 canCopy.push(entity.id);
49108             }
49109         }
49110
49111         context.copyIDs(canCopy);
49112     }
49113
49114
49115     function copy() {
49116         keybinding.on(uiCmd('⌘C'), doCopy);
49117         select(document).call(keybinding);
49118         return copy;
49119     }
49120
49121
49122     copy.off = function() {
49123         select(document).call(keybinding.off);
49124     };
49125
49126
49127     return copy;
49128 }
49129
49130 /*
49131     `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
49132
49133     * The `origin` function is expected to return an [x, y] tuple rather than an
49134       {x, y} object.
49135     * The events are `start`, `move`, and `end`.
49136       (https://github.com/mbostock/d3/issues/563)
49137     * The `start` event is not dispatched until the first cursor movement occurs.
49138       (https://github.com/mbostock/d3/pull/368)
49139     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
49140       than `x`, `y`, `dx`, and `dy` properties.
49141     * The `end` event is not dispatched if no movement occurs.
49142     * An `off` function is available that unbinds the drag's internal event handlers.
49143     * Delegation is supported via the `delegate` function.
49144
49145  */
49146 function behaviorDrag() {
49147     var event$$1 = dispatch('start', 'move', 'end'),
49148         origin = null,
49149         selector$$1 = '',
49150         filter = null,
49151         event_, target, surface;
49152
49153
49154     function d3_eventCancel() {
49155         event.stopPropagation();
49156         event.preventDefault();
49157     }
49158
49159     function eventOf(thiz, argumentz) {
49160         return function(e1) {
49161             e1.target = drag$$1;
49162             customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
49163         };
49164     }
49165
49166     var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
49167         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
49168             function () {
49169                 var selection$$1 = selection(),
49170                     select$$1 = selection$$1.style(d3_event_userSelectProperty);
49171                 selection$$1.style(d3_event_userSelectProperty, 'none');
49172                 return function () {
49173                     selection$$1.style(d3_event_userSelectProperty, select$$1);
49174                 };
49175             } :
49176             function (type) {
49177                 var w = select(window).on('selectstart.' + type, d3_eventCancel);
49178                 return function () {
49179                     w.on('selectstart.' + type, null);
49180                 };
49181             };
49182
49183
49184     function mousedown() {
49185         target = this;
49186         event_ = eventOf(target, arguments);
49187
49188         var eventTarget = event.target,
49189             touchId = event.touches ? event.changedTouches[0].identifier : null,
49190             offset,
49191             origin_ = point(),
49192             started = false,
49193             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
49194
49195         var w = select(window)
49196             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
49197             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
49198
49199         if (origin) {
49200             offset = origin.apply(target, arguments);
49201             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
49202         } else {
49203             offset = [0, 0];
49204         }
49205
49206         if (touchId === null) event.stopPropagation();
49207
49208         function point() {
49209             var p = target.parentNode || surface;
49210             return touchId !== null ? touches(p).filter(function(p) {
49211                 return p.identifier === touchId;
49212             })[0] : mouse(p);
49213         }
49214
49215
49216         function dragmove() {
49217             var p = point(),
49218                 dx = p[0] - origin_[0],
49219                 dy = p[1] - origin_[1];
49220
49221             if (dx === 0 && dy === 0)
49222                 return;
49223
49224             if (!started) {
49225                 started = true;
49226                 event_({
49227                     type: 'start'
49228                 });
49229             }
49230
49231             origin_ = p;
49232             d3_eventCancel();
49233
49234             event_({
49235                 type: 'move',
49236                 point: [p[0] + offset[0],  p[1] + offset[1]],
49237                 delta: [dx, dy]
49238             });
49239         }
49240
49241
49242         function dragend() {
49243             if (started) {
49244                 event_({
49245                     type: 'end'
49246                 });
49247
49248                 d3_eventCancel();
49249                 if (event.target === eventTarget) w.on('click.drag', click, true);
49250             }
49251
49252             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
49253                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
49254             selectEnable();
49255         }
49256
49257
49258         function click() {
49259             d3_eventCancel();
49260             w.on('click.drag', null);
49261         }
49262     }
49263
49264
49265     function drag$$1(selection$$1) {
49266         var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
49267             delegate = mousedown;
49268
49269         if (selector$$1) {
49270             delegate = function() {
49271                 var root = this,
49272                     target = event.target;
49273                 for (; target && target !== root; target = target.parentNode) {
49274                     if (target[matchesSelector](selector$$1) &&
49275                             (!filter || filter(target.__data__))) {
49276                         return mousedown.call(target, target.__data__);
49277                     }
49278                 }
49279             };
49280         }
49281
49282         selection$$1.on('mousedown.drag' + selector$$1, delegate)
49283             .on('touchstart.drag' + selector$$1, delegate);
49284     }
49285
49286
49287     drag$$1.off = function(selection$$1) {
49288         selection$$1.on('mousedown.drag' + selector$$1, null)
49289             .on('touchstart.drag' + selector$$1, null);
49290     };
49291
49292
49293     drag$$1.delegate = function(_) {
49294         if (!arguments.length) return selector$$1;
49295         selector$$1 = _;
49296         return drag$$1;
49297     };
49298
49299
49300     drag$$1.filter = function(_) {
49301         if (!arguments.length) return origin;
49302         filter = _;
49303         return drag$$1;
49304     };
49305
49306
49307     drag$$1.origin = function (_) {
49308         if (!arguments.length) return origin;
49309         origin = _;
49310         return drag$$1;
49311     };
49312
49313
49314     drag$$1.cancel = function() {
49315         select(window)
49316             .on('mousemove.drag', null)
49317             .on('mouseup.drag', null);
49318         return drag$$1;
49319     };
49320
49321
49322     drag$$1.target = function() {
49323         if (!arguments.length) return target;
49324         target = arguments[0];
49325         event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
49326         return drag$$1;
49327     };
49328
49329
49330     drag$$1.surface = function() {
49331         if (!arguments.length) return surface;
49332         surface = arguments[0];
49333         return drag$$1;
49334     };
49335
49336
49337     return utilRebind(drag$$1, event$$1, 'on');
49338 }
49339
49340 function behaviorDrawWay(context, wayId, index, mode, baseGraph) {
49341
49342     var way = context.entity(wayId),
49343         isArea = context.geometry(wayId) === 'area',
49344         finished = false,
49345         annotation = t((way.isDegenerate() ?
49346             'operations.start.annotation.' :
49347             'operations.continue.annotation.') + context.geometry(wayId)),
49348         draw = behaviorDraw(context);
49349
49350     var startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0,
49351         start = osmNode({loc: context.graph().entity(way.nodes[startIndex]).loc}),
49352         end = osmNode({loc: context.map().mouseCoordinates()}),
49353         segment = osmWay({
49354             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
49355             tags: lodash.clone(way.tags)
49356         });
49357
49358     var fn = context[way.isDegenerate() ? 'replace' : 'perform'];
49359     if (isArea) {
49360         fn(actionAddEntity(end),
49361             actionAddVertex(wayId, end.id, index)
49362         );
49363     } else {
49364         fn(actionAddEntity(start),
49365             actionAddEntity(end),
49366             actionAddEntity(segment)
49367         );
49368     }
49369
49370
49371     function move(datum) {
49372         var loc;
49373
49374         if (datum.type === 'node' && datum.id !== end.id) {
49375             loc = datum.loc;
49376
49377         } else if (datum.type === 'way' && datum.id !== segment.id) {
49378             var dims = context.map().dimensions(),
49379                 mouse = context.mouse(),
49380                 pad = 5,
49381                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
49382                     mouse[1] > pad && mouse[1] < dims[1] - pad;
49383
49384             if (trySnap) {
49385                 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
49386             }
49387         }
49388
49389         if (!loc) {
49390             loc = context.map().mouseCoordinates();
49391         }
49392
49393         context.replace(actionMoveNode(end.id, loc));
49394     }
49395
49396
49397     function undone() {
49398         finished = true;
49399         context.enter(modeBrowse$$1(context));
49400     }
49401
49402
49403     function setActiveElements() {
49404         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
49405         context.surface().selectAll(utilEntitySelector(active))
49406             .classed('active', true);
49407     }
49408
49409
49410     var drawWay = function(surface) {
49411         draw.on('move', move)
49412             .on('click', drawWay.add)
49413             .on('clickWay', drawWay.addWay)
49414             .on('clickNode', drawWay.addNode)
49415             .on('undo', context.undo)
49416             .on('cancel', drawWay.cancel)
49417             .on('finish', drawWay.finish);
49418
49419         context.map()
49420             .dblclickEnable(false)
49421             .on('drawn.draw', setActiveElements);
49422
49423         setActiveElements();
49424
49425         surface.call(draw);
49426
49427         context.history()
49428             .on('undone.draw', undone);
49429     };
49430
49431
49432     drawWay.off = function(surface) {
49433         if (!finished)
49434             context.pop();
49435
49436         context.map()
49437             .on('drawn.draw', null);
49438
49439         surface.call(draw.off)
49440             .selectAll('.active')
49441             .classed('active', false);
49442
49443         context.history()
49444             .on('undone.draw', null);
49445     };
49446
49447
49448     function ReplaceTemporaryNode(newNode) {
49449         return function(graph) {
49450             if (isArea) {
49451                 return graph
49452                     .replace(way.addNode(newNode.id, index))
49453                     .remove(end);
49454
49455             } else {
49456                 return graph
49457                     .replace(graph.entity(wayId).addNode(newNode.id, index))
49458                     .remove(end)
49459                     .remove(segment)
49460                     .remove(start);
49461             }
49462         };
49463     }
49464
49465
49466     // Accept the current position of the temporary node and continue drawing.
49467     drawWay.add = function(loc) {
49468         // prevent duplicate nodes
49469         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
49470         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
49471
49472         var newNode = osmNode({loc: loc});
49473
49474         context.replace(
49475             actionAddEntity(newNode),
49476             ReplaceTemporaryNode(newNode),
49477             annotation
49478         );
49479
49480         finished = true;
49481         context.enter(mode);
49482     };
49483
49484
49485     // Connect the way to an existing way.
49486     drawWay.addWay = function(loc, edge) {
49487         var previousEdge = startIndex ?
49488             [way.nodes[startIndex], way.nodes[startIndex - 1]] :
49489             [way.nodes[0], way.nodes[1]];
49490
49491         // Avoid creating duplicate segments
49492         if (!isArea && geoEdgeEqual(edge, previousEdge))
49493             return;
49494
49495         var newNode = osmNode({ loc: loc });
49496
49497         context.perform(
49498             actionAddMidpoint({ loc: loc, edge: edge}, newNode),
49499             ReplaceTemporaryNode(newNode),
49500             annotation
49501         );
49502
49503         finished = true;
49504         context.enter(mode);
49505     };
49506
49507
49508     // Connect the way to an existing node and continue drawing.
49509     drawWay.addNode = function(node) {
49510         // Avoid creating duplicate segments
49511         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
49512
49513         context.perform(
49514             ReplaceTemporaryNode(node),
49515             annotation
49516         );
49517
49518         finished = true;
49519         context.enter(mode);
49520     };
49521
49522
49523     // Finish the draw operation, removing the temporary node. If the way has enough
49524     // nodes to be valid, it's selected. Otherwise, return to browse mode.
49525     drawWay.finish = function() {
49526         context.pop();
49527         finished = true;
49528
49529         window.setTimeout(function() {
49530             context.map().dblclickEnable(true);
49531         }, 1000);
49532
49533         if (context.hasEntity(wayId)) {
49534             context.enter(
49535                 modeSelect(context, [wayId]).suppressMenu(true).newFeature(true)
49536             );
49537         } else {
49538             context.enter(modeBrowse$$1(context));
49539         }
49540     };
49541
49542
49543     // Cancel the draw operation and return to browse, deleting everything drawn.
49544     drawWay.cancel = function() {
49545         context.perform(
49546             utilFunctor(baseGraph),
49547             t('operations.cancel_draw.annotation'));
49548
49549         window.setTimeout(function() {
49550             context.map().dblclickEnable(true);
49551         }, 1000);
49552
49553         finished = true;
49554         context.enter(modeBrowse$$1(context));
49555     };
49556
49557
49558     drawWay.tail = function(text) {
49559         draw.tail(text);
49560         return drawWay;
49561     };
49562
49563
49564     return drawWay;
49565 }
49566
49567 function behaviorHash(context) {
49568     var s0 = null, // cached window.location.hash
49569         lat = 90 - 1e-8; // allowable latitude range
49570
49571
49572     var parser = function(map$$1, s) {
49573         var q = utilStringQs(s);
49574         var args = (q.map || '').split('/').map(Number);
49575         if (args.length < 3 || args.some(isNaN)) {
49576             return true; // replace bogus hash
49577         } else if (s !== formatter(map$$1).slice(1)) {
49578             map$$1.centerZoom([args[2],
49579                 Math.min(lat, Math.max(-lat, args[1]))], args[0]);
49580         }
49581     };
49582
49583
49584     var formatter = function(map$$1) {
49585         var mode = context.mode(),
49586             center = map$$1.center(),
49587             zoom$$1 = map$$1.zoom(),
49588             precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
49589             q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
49590             newParams = {};
49591
49592         if (mode && mode.id === 'browse') {
49593             delete q.id;
49594         } else {
49595             var selected = context.selectedIDs().filter(function(id) {
49596                 return !context.entity(id).isNew();
49597             });
49598             if (selected.length) {
49599                 newParams.id = selected.join(',');
49600             }
49601         }
49602
49603         newParams.map = zoom$$1.toFixed(2) +
49604                 '/' + center[1].toFixed(precision) +
49605                 '/' + center[0].toFixed(precision);
49606
49607         return '#' + utilQsString(lodash.assign(q, newParams), true);
49608     };
49609
49610
49611     function update() {
49612         if (context.inIntro()) return;
49613         var s1 = formatter(context.map());
49614         if (s0 !== s1) {
49615             window.location.replace(s0 = s1);  // don't recenter the map!
49616         }
49617     }
49618
49619
49620     var throttledUpdate = lodash.throttle(update, 500);
49621
49622
49623     function hashchange() {
49624         if (window.location.hash === s0) return;  // ignore spurious hashchange events
49625         if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
49626             update(); // replace bogus hash
49627         }
49628     }
49629
49630
49631     function hash() {
49632         context.map()
49633             .on('move.hash', throttledUpdate);
49634
49635         context
49636             .on('enter.hash', throttledUpdate);
49637
49638         select(window)
49639             .on('hashchange.hash', hashchange);
49640
49641         if (window.location.hash) {
49642             var q = utilStringQs(window.location.hash.substring(1));
49643             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
49644             if (q.comment) context.storage('comment', q.comment);
49645             hashchange();
49646             if (q.map) hash.hadHash = true;
49647         }
49648     }
49649
49650
49651     hash.off = function() {
49652         throttledUpdate.cancel();
49653
49654         context.map()
49655             .on('move.hash', null);
49656
49657         context
49658             .on('enter.hash', null);
49659
49660         select(window)
49661             .on('hashchange.hash', null);
49662
49663         window.location.hash = '';
49664     };
49665
49666
49667     return hash;
49668 }
49669
49670 function behaviorLasso(context) {
49671
49672     var behavior = function(selection$$1) {
49673         var lasso;
49674
49675
49676         function mousedown() {
49677             var button = 0;  // left
49678             if (event.button === button && event.shiftKey === true) {
49679                 lasso = null;
49680
49681                 selection$$1
49682                     .on('mousemove.lasso', mousemove)
49683                     .on('mouseup.lasso', mouseup);
49684
49685                 event.stopPropagation();
49686             }
49687         }
49688
49689
49690         function mousemove() {
49691             if (!lasso) {
49692                 lasso = uiLasso(context);
49693                 context.surface().call(lasso);
49694             }
49695
49696             lasso.p(context.mouse());
49697         }
49698
49699
49700         function normalize(a, b) {
49701             return [
49702                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
49703                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
49704         }
49705
49706
49707         function lassoed() {
49708             if (!lasso) return [];
49709
49710             var graph = context.graph(),
49711                 bounds = lasso.extent().map(context.projection.invert),
49712                 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
49713
49714             return lodash.map(context.intersects(extent$$1).filter(function(entity) {
49715                 return entity.type === 'node' &&
49716                     geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
49717                     !context.features().isHidden(entity, graph, entity.geometry(graph));
49718             }), 'id');
49719         }
49720
49721
49722         function mouseup() {
49723             selection$$1
49724                 .on('mousemove.lasso', null)
49725                 .on('mouseup.lasso', null);
49726
49727             if (!lasso) return;
49728
49729             var ids = lassoed();
49730             lasso.close();
49731
49732             if (ids.length) {
49733                 context.enter(modeSelect(context, ids));
49734             }
49735         }
49736
49737         selection$$1
49738             .on('mousedown.lasso', mousedown);
49739     };
49740
49741
49742     behavior.off = function(selection$$1) {
49743         selection$$1.on('mousedown.lasso', null);
49744     };
49745
49746
49747     return behavior;
49748 }
49749
49750 function behaviorPaste(context) {
49751     var keybinding = d3keybinding('paste');
49752
49753     function omitTag(v, k) {
49754         return (
49755             k === 'phone' ||
49756             k === 'fax' ||
49757             k === 'email' ||
49758             k === 'website' ||
49759             k === 'url' ||
49760             k === 'note' ||
49761             k === 'description' ||
49762             k.indexOf('name') !== -1 ||
49763             k.indexOf('wiki') === 0 ||
49764             k.indexOf('addr:') === 0 ||
49765             k.indexOf('contact:') === 0
49766         );
49767     }
49768
49769
49770     function doPaste() {
49771         event.preventDefault();
49772         if (context.inIntro()) return;
49773
49774         var baseGraph = context.graph(),
49775             mouse$$1 = context.mouse(),
49776             projection = context.projection,
49777             viewport = geoExtent$$1(projection.clipExtent()).polygon();
49778
49779         if (!geoPointInPolygon(mouse$$1, viewport)) return;
49780
49781         var extent$$1 = geoExtent$$1(),
49782             oldIDs = context.copyIDs(),
49783             oldGraph = context.copyGraph(),
49784             newIDs = [];
49785
49786         if (!oldIDs.length) return;
49787
49788         var action = actionCopyEntities(oldIDs, oldGraph);
49789         context.perform(action);
49790
49791         var copies = action.copies();
49792         for (var id in copies) {
49793             var oldEntity = oldGraph.entity(id),
49794                 newEntity = copies[id];
49795
49796             extent$$1._extend(oldEntity.extent(oldGraph));
49797             newIDs.push(newEntity.id);
49798             context.perform(
49799                 actionChangeTags(newEntity.id, lodash.omit(newEntity.tags, omitTag))
49800             );
49801         }
49802
49803         // Put pasted objects where mouse pointer is..
49804         var center = projection(extent$$1.center()),
49805             delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
49806
49807         context.perform(actionMove(newIDs, delta, projection));
49808         context.enter(modeMove$$1(context, newIDs, baseGraph));
49809     }
49810
49811
49812     function paste() {
49813         keybinding.on(uiCmd('⌘V'), doPaste);
49814         select(document).call(keybinding);
49815         return paste;
49816     }
49817
49818
49819     paste.off = function() {
49820         select(document).call(keybinding.off);
49821     };
49822
49823
49824     return paste;
49825 }
49826
49827 function behaviorSelect(context) {
49828
49829     function keydown() {
49830         if (event && event.shiftKey) {
49831             context.surface()
49832                 .classed('behavior-multiselect', true);
49833         }
49834     }
49835
49836
49837     function keyup() {
49838         if (!event || !event.shiftKey) {
49839             context.surface()
49840                 .classed('behavior-multiselect', false);
49841         }
49842     }
49843
49844
49845     function click() {
49846         var datum = event.target.__data__,
49847             lasso = select('#surface .lasso').node(),
49848             mode = context.mode();
49849
49850         if (!(datum instanceof osmEntity$$1)) {
49851             if (!event.shiftKey && !lasso && mode.id !== 'browse')
49852                 context.enter(modeBrowse$$1(context));
49853
49854         } else if (!event.shiftKey && !lasso) {
49855             // Avoid re-entering Select mode with same entity.
49856             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
49857                 context.enter(modeSelect(context, [datum.id]));
49858             } else {
49859                 mode.suppressMenu(false).reselect();
49860             }
49861         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
49862             var selectedIDs = lodash.without(context.selectedIDs(), datum.id);
49863             context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse$$1(context));
49864
49865         } else {
49866             context.enter(modeSelect(context, context.selectedIDs().concat([datum.id])));
49867         }
49868     }
49869
49870
49871     var behavior = function(selection$$1) {
49872         select(window)
49873             .on('keydown.select', keydown)
49874             .on('keyup.select', keyup);
49875
49876         selection$$1.on('click.select', click);
49877
49878         keydown();
49879     };
49880
49881
49882     behavior.off = function(selection$$1) {
49883         select(window)
49884             .on('keydown.select', null)
49885             .on('keyup.select', null);
49886
49887         selection$$1.on('click.select', null);
49888
49889         keyup();
49890     };
49891
49892
49893     return behavior;
49894 }
49895
49896 function modeAddArea$$1(context) {
49897     var mode = {
49898         id: 'add-area',
49899         button: 'area',
49900         title: t('modes.add_area.title'),
49901         description: t('modes.add_area.description'),
49902         key: '3'
49903     };
49904
49905     var behavior = behaviorAddWay(context)
49906             .tail(t('modes.add_area.tail'))
49907             .on('start', start)
49908             .on('startFromWay', startFromWay)
49909             .on('startFromNode', startFromNode),
49910         defaultTags = { area: 'yes' };
49911
49912
49913     function start(loc) {
49914         var graph = context.graph(),
49915             node = osmNode({ loc: loc }),
49916             way = osmWay({ tags: defaultTags });
49917
49918         context.perform(
49919             actionAddEntity(node),
49920             actionAddEntity(way),
49921             actionAddVertex(way.id, node.id),
49922             actionAddVertex(way.id, node.id)
49923         );
49924
49925         context.enter(modeDrawArea(context, way.id, graph));
49926     }
49927
49928
49929     function startFromWay(loc, edge) {
49930         var graph = context.graph(),
49931             node = osmNode({ loc: loc }),
49932             way = osmWay({ tags: defaultTags });
49933
49934         context.perform(
49935             actionAddEntity(node),
49936             actionAddEntity(way),
49937             actionAddVertex(way.id, node.id),
49938             actionAddVertex(way.id, node.id),
49939             actionAddMidpoint({ loc: loc, edge: edge }, node)
49940         );
49941
49942         context.enter(modeDrawArea(context, way.id, graph));
49943     }
49944
49945
49946     function startFromNode(node) {
49947         var graph = context.graph(),
49948             way = osmWay({ tags: defaultTags });
49949
49950         context.perform(
49951             actionAddEntity(way),
49952             actionAddVertex(way.id, node.id),
49953             actionAddVertex(way.id, node.id)
49954         );
49955
49956         context.enter(modeDrawArea(context, way.id, graph));
49957     }
49958
49959
49960     mode.enter = function() {
49961         context.install(behavior);
49962     };
49963
49964
49965     mode.exit = function() {
49966         context.uninstall(behavior);
49967     };
49968
49969
49970     return mode;
49971 }
49972
49973 function modeAddLine$$1(context) {
49974     var mode = {
49975         id: 'add-line',
49976         button: 'line',
49977         title: t('modes.add_line.title'),
49978         description: t('modes.add_line.description'),
49979         key: '2'
49980     };
49981
49982     var behavior = behaviorAddWay(context)
49983         .tail(t('modes.add_line.tail'))
49984         .on('start', start)
49985         .on('startFromWay', startFromWay)
49986         .on('startFromNode', startFromNode);
49987
49988
49989     function start(loc) {
49990         var baseGraph = context.graph(),
49991             node = osmNode({ loc: loc }),
49992             way = osmWay();
49993
49994         context.perform(
49995             actionAddEntity(node),
49996             actionAddEntity(way),
49997             actionAddVertex(way.id, node.id)
49998         );
49999
50000         context.enter(modeDrawLine(context, way.id, baseGraph));
50001     }
50002
50003
50004     function startFromWay(loc, edge) {
50005         var baseGraph = context.graph(),
50006             node = osmNode({ loc: loc }),
50007             way = osmWay();
50008
50009         context.perform(
50010             actionAddEntity(node),
50011             actionAddEntity(way),
50012             actionAddVertex(way.id, node.id),
50013             actionAddMidpoint({ loc: loc, edge: edge }, node)
50014         );
50015
50016         context.enter(modeDrawLine(context, way.id, baseGraph));
50017     }
50018
50019
50020     function startFromNode(node) {
50021         var baseGraph = context.graph(),
50022             way = osmWay();
50023
50024         context.perform(
50025             actionAddEntity(way),
50026             actionAddVertex(way.id, node.id)
50027         );
50028
50029         context.enter(modeDrawLine(context, way.id, baseGraph));
50030     }
50031
50032
50033     mode.enter = function() {
50034         context.install(behavior);
50035     };
50036
50037
50038     mode.exit = function() {
50039         context.uninstall(behavior);
50040     };
50041
50042     return mode;
50043 }
50044
50045 function modeAddPoint$$1(context) {
50046     var mode = {
50047         id: 'add-point',
50048         button: 'point',
50049         title: t('modes.add_point.title'),
50050         description: t('modes.add_point.description'),
50051         key: '1'
50052     };
50053
50054     var behavior = behaviorDraw(context)
50055         .tail(t('modes.add_point.tail'))
50056         .on('click', add)
50057         .on('clickWay', addWay)
50058         .on('clickNode', addNode)
50059         .on('cancel', cancel)
50060         .on('finish', cancel);
50061
50062
50063     function add(loc) {
50064         var node = osmNode({ loc: loc });
50065
50066         context.perform(
50067             actionAddEntity(node),
50068             t('operations.add.annotation.point')
50069         );
50070
50071         context.enter(
50072             modeSelect(context, [node.id]).suppressMenu(true).newFeature(true)
50073         );
50074     }
50075
50076
50077     function addWay(loc) {
50078         add(loc);
50079     }
50080
50081
50082     function addNode(node) {
50083         add(node.loc);
50084     }
50085
50086
50087     function cancel() {
50088         context.enter(modeBrowse$$1(context));
50089     }
50090
50091
50092     mode.enter = function() {
50093         context.install(behavior);
50094     };
50095
50096
50097     mode.exit = function() {
50098         context.uninstall(behavior);
50099     };
50100
50101
50102     return mode;
50103 }
50104
50105 function modeBrowse$$1(context) {
50106     var mode = {
50107         button: 'browse',
50108         id: 'browse',
50109         title: t('modes.browse.title'),
50110         description: t('modes.browse.description')
50111     }, sidebar;
50112
50113     var behaviors = [
50114         behaviorPaste(context),
50115         behaviorHover(context).on('hover', context.ui().sidebar.hover),
50116         behaviorSelect(context),
50117         behaviorLasso(context),
50118         modeDragNode$$1(context).behavior
50119     ];
50120
50121
50122     mode.enter = function() {
50123         behaviors.forEach(function(behavior) {
50124             context.install(behavior);
50125         });
50126
50127         // Get focus on the body.
50128         if (document.activeElement && document.activeElement.blur) {
50129             document.activeElement.blur();
50130         }
50131
50132         if (sidebar) {
50133             context.ui().sidebar.show(sidebar);
50134         } else {
50135             context.ui().sidebar.select(null);
50136         }
50137     };
50138
50139
50140     mode.exit = function() {
50141         context.ui().sidebar.hover.cancel();
50142         behaviors.forEach(function(behavior) {
50143             context.uninstall(behavior);
50144         });
50145
50146         if (sidebar) {
50147             context.ui().sidebar.hide();
50148         }
50149     };
50150
50151
50152     mode.sidebar = function(_) {
50153         if (!arguments.length) return sidebar;
50154         sidebar = _;
50155         return mode;
50156     };
50157
50158
50159     return mode;
50160 }
50161
50162 function modeDragNode$$1(context) {
50163     var mode = {
50164         id: 'drag-node',
50165         button: 'browse'
50166     };
50167
50168     var nudgeInterval,
50169         activeIDs,
50170         wasMidpoint,
50171         isCancelled,
50172         selectedIDs = [],
50173         hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
50174         edit = behaviorEdit(context);
50175
50176
50177     function edge(point, size) {
50178         var pad = [30, 100, 30, 100];
50179         if (point[0] > size[0] - pad[0]) return [-10, 0];
50180         else if (point[0] < pad[2]) return [10, 0];
50181         else if (point[1] > size[1] - pad[1]) return [0, -10];
50182         else if (point[1] < pad[3]) return [0, 10];
50183         return null;
50184     }
50185
50186
50187     function startNudge(nudge) {
50188         if (nudgeInterval) window.clearInterval(nudgeInterval);
50189         nudgeInterval = window.setInterval(function() {
50190             context.pan(nudge);
50191         }, 50);
50192     }
50193
50194
50195     function stopNudge() {
50196         if (nudgeInterval) window.clearInterval(nudgeInterval);
50197         nudgeInterval = null;
50198     }
50199
50200
50201     function moveAnnotation(entity) {
50202         return t('operations.move.annotation.' + entity.geometry(context.graph()));
50203     }
50204
50205
50206     function connectAnnotation(entity) {
50207         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
50208     }
50209
50210
50211     function origin(entity) {
50212         return context.projection(entity.loc);
50213     }
50214
50215
50216     function start(entity) {
50217         isCancelled = event.sourceEvent.shiftKey ||
50218             context.features().hasHiddenConnections(entity, context.graph());
50219
50220         if (isCancelled) return behavior.cancel();
50221
50222         wasMidpoint = entity.type === 'midpoint';
50223         if (wasMidpoint) {
50224             var midpoint = entity;
50225             entity = osmNode();
50226             context.perform(actionAddMidpoint(midpoint, entity));
50227
50228             var vertex = context.surface().selectAll('.' + entity.id);
50229             behavior.target(vertex.node(), entity);
50230
50231         } else {
50232             context.perform(actionNoop());
50233         }
50234
50235         activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
50236         activeIDs.push(entity.id);
50237         context.enter(mode);
50238     }
50239
50240
50241     function datum() {
50242         if (event.sourceEvent.altKey) {
50243             return {};
50244         }
50245
50246         return event.sourceEvent.target.__data__ || {};
50247     }
50248
50249
50250     // via https://gist.github.com/shawnbot/4166283
50251     function childOf(p, c) {
50252         if (p === c) return false;
50253         while (c && c !== p) c = c.parentNode;
50254         return c === p;
50255     }
50256
50257
50258     function move(entity) {
50259         if (isCancelled) return;
50260         event.sourceEvent.stopPropagation();
50261
50262         var nudge = childOf(context.container().node(),
50263             event.sourceEvent.toElement) &&
50264             edge(event.point, context.map().dimensions());
50265
50266         if (nudge) startNudge(nudge);
50267         else stopNudge();
50268
50269         var loc = context.projection.invert(event.point);
50270
50271         var d = datum();
50272         if (d.type === 'node' && d.id !== entity.id) {
50273             loc = d.loc;
50274         } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
50275             loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
50276         }
50277
50278         context.replace(
50279             actionMoveNode(entity.id, loc),
50280             moveAnnotation(entity)
50281         );
50282     }
50283
50284
50285     function end(entity) {
50286         if (isCancelled) return;
50287
50288         var d = datum();
50289
50290         if (d.type === 'way') {
50291             var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
50292             context.replace(
50293                 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
50294                 connectAnnotation(d)
50295             );
50296
50297         } else if (d.type === 'node' && d.id !== entity.id) {
50298             context.replace(
50299                 actionConnect([d.id, entity.id]),
50300                 connectAnnotation(d)
50301             );
50302
50303         } else if (wasMidpoint) {
50304             context.replace(
50305                 actionNoop(),
50306                 t('operations.add.annotation.vertex')
50307             );
50308
50309         } else {
50310             context.replace(
50311                 actionNoop(),
50312                 moveAnnotation(entity)
50313             );
50314         }
50315
50316         var reselection = selectedIDs.filter(function(id) {
50317             return context.graph().hasEntity(id);
50318         });
50319
50320         if (reselection.length) {
50321             context.enter(modeSelect(context, reselection).suppressMenu(true));
50322         } else {
50323             context.enter(modeBrowse$$1(context));
50324         }
50325     }
50326
50327
50328     function cancel() {
50329         behavior.cancel();
50330         context.enter(modeBrowse$$1(context));
50331     }
50332
50333
50334     function setActiveElements() {
50335         context.surface().selectAll(utilEntitySelector(activeIDs))
50336             .classed('active', true);
50337     }
50338
50339
50340     var behavior = behaviorDrag()
50341         .delegate('g.node, g.point, g.midpoint')
50342         .surface(context.surface().node())
50343         .origin(origin)
50344         .on('start', start)
50345         .on('move', move)
50346         .on('end', end);
50347
50348
50349     mode.enter = function() {
50350         context.install(hover);
50351         context.install(edit);
50352
50353         context.history()
50354             .on('undone.drag-node', cancel);
50355
50356         context.map()
50357             .on('drawn.drag-node', setActiveElements);
50358
50359         setActiveElements();
50360     };
50361
50362
50363     mode.exit = function() {
50364         context.ui().sidebar.hover.cancel();
50365         context.uninstall(hover);
50366         context.uninstall(edit);
50367
50368         context.history()
50369             .on('undone.drag-node', null);
50370
50371         context.map()
50372             .on('drawn.drag-node', null);
50373
50374         context.surface()
50375             .selectAll('.active')
50376             .classed('active', false);
50377
50378         stopNudge();
50379     };
50380
50381
50382     mode.selectedIDs = function(_) {
50383         if (!arguments.length) return selectedIDs;
50384         selectedIDs = _;
50385         return mode;
50386     };
50387
50388
50389     mode.behavior = behavior;
50390
50391
50392     return mode;
50393 }
50394
50395 function modeDrawArea(context, wayId, baseGraph) {
50396     var mode = {
50397         button: 'area',
50398         id: 'draw-area'
50399     };
50400
50401     var behavior;
50402
50403
50404     mode.enter = function() {
50405         var way = context.entity(wayId),
50406             headId = way.nodes[way.nodes.length - 2],
50407             tailId = way.first();
50408
50409         behavior = behaviorDrawWay(context, wayId, -1, mode, baseGraph)
50410             .tail(t('modes.draw_area.tail'));
50411
50412         var addNode = behavior.addNode;
50413
50414         behavior.addNode = function(node) {
50415             if (node.id === headId || node.id === tailId) {
50416                 behavior.finish();
50417             } else {
50418                 addNode(node);
50419             }
50420         };
50421
50422         context.install(behavior);
50423     };
50424
50425
50426     mode.exit = function() {
50427         context.uninstall(behavior);
50428     };
50429
50430
50431     mode.selectedIDs = function() {
50432         return [wayId];
50433     };
50434
50435
50436     return mode;
50437 }
50438
50439 function modeDrawLine(context, wayId, baseGraph, affix) {
50440     var mode = {
50441         button: 'line',
50442         id: 'draw-line'
50443     };
50444
50445     var behavior;
50446
50447
50448     mode.enter = function() {
50449         var way = context.entity(wayId),
50450             index = (affix === 'prefix') ? 0 : undefined,
50451             headId = (affix === 'prefix') ? way.first() : way.last();
50452
50453         behavior = behaviorDrawWay(context, wayId, index, mode, baseGraph)
50454             .tail(t('modes.draw_line.tail'));
50455
50456         var addNode = behavior.addNode;
50457
50458         behavior.addNode = function(node) {
50459             if (node.id === headId) {
50460                 behavior.finish();
50461             } else {
50462                 addNode(node);
50463             }
50464         };
50465
50466         context.install(behavior);
50467     };
50468
50469
50470     mode.exit = function() {
50471         context.uninstall(behavior);
50472     };
50473
50474
50475     mode.selectedIDs = function() {
50476         return [wayId];
50477     };
50478
50479
50480     return mode;
50481 }
50482
50483 function modeMove$$1(context, entityIDs, baseGraph) {
50484     var mode = {
50485         id: 'move',
50486         button: 'browse'
50487     };
50488
50489     var keybinding = d3keybinding('move'),
50490         edit = behaviorEdit(context),
50491         annotation = entityIDs.length === 1 ?
50492             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
50493             t('operations.move.annotation.multiple'),
50494         cache,
50495         origin,
50496         nudgeInterval;
50497
50498
50499     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
50500
50501
50502     function edge(point, size) {
50503         var pad = [30, 100, 30, 100];
50504         if (point[0] > size[0] - pad[0]) return [-10, 0];
50505         else if (point[0] < pad[2]) return [10, 0];
50506         else if (point[1] > size[1] - pad[1]) return [0, -10];
50507         else if (point[1] < pad[3]) return [0, 10];
50508         return null;
50509     }
50510
50511
50512     function startNudge(nudge) {
50513         if (nudgeInterval) window.clearInterval(nudgeInterval);
50514         nudgeInterval = window.setInterval(function() {
50515             context.pan(nudge);
50516
50517             var currMouse = context.mouse(),
50518                 origMouse = context.projection(origin),
50519                 delta = vecSub(vecSub(currMouse, origMouse), nudge),
50520                 action = actionMove(entityIDs, delta, context.projection, cache);
50521
50522             context.overwrite(action, annotation);
50523
50524         }, 50);
50525     }
50526
50527
50528     function stopNudge() {
50529         if (nudgeInterval) window.clearInterval(nudgeInterval);
50530         nudgeInterval = null;
50531     }
50532
50533
50534     function move() {
50535         var currMouse = context.mouse(),
50536             origMouse = context.projection(origin),
50537             delta = vecSub(currMouse, origMouse),
50538             action = actionMove(entityIDs, delta, context.projection, cache);
50539
50540         context.overwrite(action, annotation);
50541
50542         var nudge = edge(currMouse, context.map().dimensions());
50543         if (nudge) startNudge(nudge);
50544         else stopNudge();
50545     }
50546
50547
50548     function finish() {
50549         event.stopPropagation();
50550         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
50551         stopNudge();
50552     }
50553
50554
50555     function cancel() {
50556         if (baseGraph) {
50557             while (context.graph() !== baseGraph) context.pop();
50558             context.enter(modeBrowse$$1(context));
50559         } else {
50560             context.pop();
50561             context.enter(modeSelect(context, entityIDs).suppressMenu(true));
50562         }
50563         stopNudge();
50564     }
50565
50566
50567     function undone() {
50568         context.enter(modeBrowse$$1(context));
50569     }
50570
50571
50572     mode.enter = function() {
50573         origin = context.map().mouseCoordinates();
50574         cache = {};
50575
50576         context.install(edit);
50577
50578         context.perform(
50579             actionNoop(),
50580             annotation
50581         );
50582
50583         context.surface()
50584             .on('mousemove.move', move)
50585             .on('click.move', finish);
50586
50587         context.history()
50588             .on('undone.move', undone);
50589
50590         keybinding
50591             .on('⎋', cancel)
50592             .on('↩', finish);
50593
50594         select(document)
50595             .call(keybinding);
50596     };
50597
50598
50599     mode.exit = function() {
50600         stopNudge();
50601
50602         context.uninstall(edit);
50603
50604         context.surface()
50605             .on('mousemove.move', null)
50606             .on('click.move', null);
50607
50608         context.history()
50609             .on('undone.move', null);
50610
50611         keybinding.off();
50612     };
50613
50614
50615     return mode;
50616 }
50617
50618 function modeRotateWay$$1(context, wayId) {
50619     var mode = {
50620         id: 'rotate-way',
50621         button: 'browse'
50622     };
50623
50624     var keybinding = d3keybinding('rotate-way'),
50625         edit = behaviorEdit(context);
50626
50627
50628     mode.enter = function() {
50629         context.install(edit);
50630
50631         var annotation = t('operations.rotate.annotation.' + context.geometry(wayId)),
50632             way = context.graph().entity(wayId),
50633             nodes = lodash.uniq(context.graph().childNodes(way)),
50634             points = nodes.map(function(n) { return context.projection(n.loc); }),
50635             pivot = d3polygonCentroid(points),
50636             angle;
50637
50638         context.perform(
50639             actionNoop(),
50640             annotation
50641         );
50642
50643         context.surface()
50644             .on('mousemove.rotate-way', rotate)
50645             .on('click.rotate-way', finish);
50646
50647         context.history()
50648             .on('undone.rotate-way', undone);
50649
50650         keybinding
50651             .on('⎋', cancel)
50652             .on('↩', finish);
50653
50654         select(document)
50655             .call(keybinding);
50656
50657
50658         function rotate() {
50659             var mousePoint = context.mouse(),
50660                 newAngle = Math.atan2(mousePoint[1] - pivot[1], mousePoint[0] - pivot[0]);
50661
50662             if (typeof angle === 'undefined') angle = newAngle;
50663
50664             context.replace(
50665                 actionRotateWay(wayId, pivot, newAngle - angle, context.projection),
50666                 annotation
50667             );
50668
50669             angle = newAngle;
50670         }
50671
50672
50673         function finish() {
50674             event.stopPropagation();
50675             context.enter(modeSelect(context, [wayId]).suppressMenu(true));
50676         }
50677
50678
50679         function cancel() {
50680             context.pop();
50681             context.enter(modeSelect(context, [wayId]).suppressMenu(true));
50682         }
50683
50684
50685         function undone() {
50686             context.enter(modeBrowse$$1(context));
50687         }
50688     };
50689
50690
50691     mode.exit = function() {
50692         context.uninstall(edit);
50693
50694         context.surface()
50695             .on('mousemove.rotate-way', null)
50696             .on('click.rotate-way', null);
50697
50698         context.history()
50699             .on('undone.rotate-way', null);
50700
50701         keybinding.off();
50702     };
50703
50704
50705     return mode;
50706 }
50707
50708 function modeSave$$1(context) {
50709     var mode = {
50710         id: 'save'
50711     };
50712
50713     var ui = uiCommit(context)
50714             .on('cancel', cancel)
50715             .on('save', save);
50716
50717
50718     function cancel() {
50719         context.enter(modeBrowse$$1(context));
50720     }
50721
50722
50723     function save(e, tryAgain) {
50724         function withChildNodes(ids, graph) {
50725             return lodash.uniq(lodash.reduce(ids, function(result, id) {
50726                 var e = graph.entity(id);
50727                 if (e.type === 'way') {
50728                     try {
50729                         var cn = graph.childNodes(e);
50730                         result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
50731                     } catch (err) {
50732                         /* eslint-disable no-console */
50733                         if (typeof console !== 'undefined') console.error(err);
50734                         /* eslint-enable no-console */
50735                     }
50736                 }
50737                 return result;
50738             }, lodash.clone(ids)));
50739         }
50740
50741         var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
50742             history = context.history(),
50743             origChanges = history.changes(actionDiscardTags(history.difference())),
50744             localGraph = context.graph(),
50745             remoteGraph = coreGraph$$1(history.base(), true),
50746             modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
50747             toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
50748             toLoad = withChildNodes(toCheck, localGraph),
50749             conflicts = [],
50750             errors = [];
50751
50752         if (!tryAgain) history.perform(actionNoop());  // checkpoint
50753         context.container().call(loading);
50754
50755         if (toCheck.length) {
50756             context.connection().loadMultiple(toLoad, loaded);
50757         } else {
50758             finalize();
50759         }
50760
50761
50762         // Reload modified entities into an alternate graph and check for conflicts..
50763         function loaded(err, result) {
50764             if (errors.length) return;
50765
50766             if (err) {
50767                 errors.push({
50768                     msg: err.responseText,
50769                     details: [ t('save.status_code', { code: err.status }) ]
50770                 });
50771                 showErrors();
50772
50773             } else {
50774                 var loadMore = [];
50775                 lodash.each(result.data, function(entity) {
50776                     remoteGraph.replace(entity);
50777                     toLoad = lodash.without(toLoad, entity.id);
50778
50779                     // Because loadMultiple doesn't download /full like loadEntity,
50780                     // need to also load children that aren't already being checked..
50781                     if (!entity.visible) return;
50782                     if (entity.type === 'way') {
50783                         loadMore.push.apply(loadMore,
50784                             lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
50785                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
50786                         loadMore.push.apply(loadMore,
50787                             lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
50788                     }
50789                 });
50790
50791                 if (loadMore.length) {
50792                     toLoad.push.apply(toLoad, loadMore);
50793                     context.connection().loadMultiple(loadMore, loaded);
50794                 }
50795
50796                 if (!toLoad.length) {
50797                     checkConflicts();
50798                 }
50799             }
50800         }
50801
50802
50803         function checkConflicts() {
50804             function choice(id, text$$1, action) {
50805                 return { id: id, text: text$$1, action: function() { history.replace(action); } };
50806             }
50807             function formatUser(d) {
50808                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
50809             }
50810             function entityName(entity) {
50811                 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
50812             }
50813
50814             function compareVersions(local$$1, remote) {
50815                 if (local$$1.version !== remote.version) return false;
50816
50817                 if (local$$1.type === 'way') {
50818                     var children = lodash.union(local$$1.nodes, remote.nodes);
50819
50820                     for (var i = 0; i < children.length; i++) {
50821                         var a = localGraph.hasEntity(children[i]),
50822                             b = remoteGraph.hasEntity(children[i]);
50823
50824                         if (a && b && a.version !== b.version) return false;
50825                     }
50826                 }
50827
50828                 return true;
50829             }
50830
50831             lodash.each(toCheck, function(id) {
50832                 var local$$1 = localGraph.entity(id),
50833                     remote = remoteGraph.entity(id);
50834
50835                 if (compareVersions(local$$1, remote)) return;
50836
50837                 var action = actionMergeRemoteChanges,
50838                     merge$$1 = action(id, localGraph, remoteGraph, formatUser);
50839
50840                 history.replace(merge$$1);
50841
50842                 var mergeConflicts = merge$$1.conflicts();
50843                 if (!mergeConflicts.length) return;  // merged safely
50844
50845                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
50846                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
50847                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
50848                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
50849
50850                 conflicts.push({
50851                     id: id,
50852                     name: entityName(local$$1),
50853                     details: mergeConflicts,
50854                     chosen: 1,
50855                     choices: [
50856                         choice(id, keepMine, forceLocal),
50857                         choice(id, keepTheirs, forceRemote)
50858                     ]
50859                 });
50860             });
50861
50862             finalize();
50863         }
50864
50865
50866         function finalize() {
50867             if (conflicts.length) {
50868                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
50869                 showConflicts();
50870             } else if (errors.length) {
50871                 showErrors();
50872             } else {
50873                 var changes = history.changes(actionDiscardTags(history.difference()));
50874                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
50875                     context.connection().putChangeset(
50876                         changes,
50877                         context.version,
50878                         e.comment,
50879                         history.imageryUsed(),
50880                         function(err, changeset_id) {
50881                             if (err) {
50882                                 errors.push({
50883                                     msg: err.responseText,
50884                                     details: [ t('save.status_code', { code: err.status }) ]
50885                                 });
50886                                 showErrors();
50887                             } else {
50888                                 history.clearSaved();
50889                                 success(e, changeset_id);
50890                                 // Add delay to allow for postgres replication #1646 #2678
50891                                 window.setTimeout(function() {
50892                                     loading.close();
50893                                     context.flush();
50894                                 }, 2500);
50895                             }
50896                         });
50897                 } else {        // changes were insignificant or reverted by user
50898                     loading.close();
50899                     context.flush();
50900                     cancel();
50901                 }
50902             }
50903         }
50904
50905
50906         function showConflicts() {
50907             var selection$$1 = context.container()
50908                 .select('#sidebar')
50909                 .append('div')
50910                 .attr('class','sidebar-component');
50911
50912             loading.close();
50913
50914             selection$$1.call(uiConflicts(context)
50915                 .list(conflicts)
50916                 .on('download', function() {
50917                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
50918                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
50919                     win.focus();
50920                 })
50921                 .on('cancel', function() {
50922                     history.pop();
50923                     selection$$1.remove();
50924                 })
50925                 .on('save', function() {
50926                     for (var i = 0; i < conflicts.length; i++) {
50927                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
50928                             var entity = context.hasEntity(conflicts[i].id);
50929                             if (entity && entity.type === 'way') {
50930                                 var children = lodash.uniq(entity.nodes);
50931                                 for (var j = 0; j < children.length; j++) {
50932                                     history.replace(actionRevert(children[j]));
50933                                 }
50934                             }
50935                             history.replace(actionRevert(conflicts[i].id));
50936                         }
50937                     }
50938
50939                     selection$$1.remove();
50940                     save(e, true);
50941                 })
50942             );
50943         }
50944
50945
50946         function showErrors() {
50947             var selection$$1 = uiConfirm(context.container());
50948
50949             history.pop();
50950             loading.close();
50951
50952             selection$$1
50953                 .select('.modal-section.header')
50954                 .append('h3')
50955                 .text(t('save.error'));
50956
50957             addErrors(selection$$1, errors);
50958             selection$$1.okButton();
50959         }
50960
50961
50962         function addErrors(selection$$1, data) {
50963             var message = selection$$1
50964                 .select('.modal-section.message-text');
50965
50966             var items = message
50967                 .selectAll('.error-container')
50968                 .data(data);
50969
50970             var enter = items.enter()
50971                 .append('div')
50972                 .attr('class', 'error-container');
50973
50974             enter
50975                 .append('a')
50976                 .attr('class', 'error-description')
50977                 .attr('href', '#')
50978                 .classed('hide-toggle', true)
50979                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
50980                 .on('click', function() {
50981                     var error = select(this),
50982                         detail = select(this.nextElementSibling),
50983                         exp = error.classed('expanded');
50984
50985                     detail.style('display', exp ? 'none' : 'block');
50986                     error.classed('expanded', !exp);
50987
50988                     event.preventDefault();
50989                 });
50990
50991             var details = enter
50992                 .append('div')
50993                 .attr('class', 'error-detail-container')
50994                 .style('display', 'none');
50995
50996             details
50997                 .append('ul')
50998                 .attr('class', 'error-detail-list')
50999                 .selectAll('li')
51000                 .data(function(d) { return d.details || []; })
51001                 .enter()
51002                 .append('li')
51003                 .attr('class', 'error-detail-item')
51004                 .text(function(d) { return d; });
51005
51006             items.exit()
51007                 .remove();
51008         }
51009
51010     }
51011
51012
51013     function success(e, changeset_id) {
51014         context.enter(modeBrowse$$1(context)
51015             .sidebar(uiSuccess(context)
51016                 .changeset({
51017                     id: changeset_id,
51018                     comment: e.comment
51019                 })
51020                 .on('cancel', function() {
51021                     context.ui().sidebar.hide();
51022                 })
51023             )
51024         );
51025     }
51026
51027
51028     mode.enter = function() {
51029         context.connection().authenticate(function(err) {
51030             if (err) {
51031                 cancel();
51032             } else {
51033                 context.ui().sidebar.show(ui);
51034             }
51035         });
51036     };
51037
51038
51039     mode.exit = function() {
51040         context.ui().sidebar.hide();
51041     };
51042
51043     return mode;
51044 }
51045
51046 function operationCircularize(selectedIDs, context) {
51047     var entityId = selectedIDs[0],
51048         entity = context.entity(entityId),
51049         extent = entity.extent(context.graph()),
51050         geometry = context.geometry(entityId),
51051         action = actionCircularize(entityId, context.projection);
51052
51053     var operation = function() {
51054         var annotation = t('operations.circularize.annotation.' + geometry);
51055         context.perform(action, annotation);
51056     };
51057
51058
51059     operation.available = function() {
51060         return selectedIDs.length === 1 &&
51061             entity.type === 'way' &&
51062             lodash.uniq(entity.nodes).length > 1;
51063     };
51064
51065
51066     operation.disabled = function() {
51067         var reason;
51068         if (extent.percentContainedIn(context.extent()) < 0.8) {
51069             reason = 'too_large';
51070         } else if (context.hasHiddenConnections(entityId)) {
51071             reason = 'connected_to_hidden';
51072         }
51073         return action.disabled(context.graph()) || reason;
51074     };
51075
51076
51077     operation.tooltip = function() {
51078         var disable = operation.disabled();
51079         return disable ?
51080             t('operations.circularize.' + disable) :
51081             t('operations.circularize.description.' + geometry);
51082     };
51083
51084
51085     operation.id = 'circularize';
51086     operation.keys = [t('operations.circularize.key')];
51087     operation.title = t('operations.circularize.title');
51088
51089
51090     return operation;
51091 }
51092
51093 function operationContinue(selectedIDs, context) {
51094     var graph = context.graph(),
51095         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51096         geometries = lodash.extend({ line: [], vertex: [] },
51097             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51098         vertex = geometries.vertex[0];
51099
51100
51101     function candidateWays() {
51102         return graph.parentWays(vertex).filter(function(parent) {
51103             return parent.geometry(graph) === 'line' &&
51104                 parent.affix(vertex.id) &&
51105                 (geometries.line.length === 0 || geometries.line[0] === parent);
51106         });
51107     }
51108
51109
51110     var operation = function() {
51111         var candidate = candidateWays()[0];
51112         context.enter(
51113             modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51114         );
51115     };
51116
51117
51118     operation.available = function() {
51119         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51120             !context.features().hasHiddenConnections(vertex, context.graph());
51121     };
51122
51123
51124     operation.disabled = function() {
51125         var candidates = candidateWays();
51126         if (candidates.length === 0)
51127             return 'not_eligible';
51128         if (candidates.length > 1)
51129             return 'multiple';
51130     };
51131
51132
51133     operation.tooltip = function() {
51134         var disable = operation.disabled();
51135         return disable ?
51136             t('operations.continue.' + disable) :
51137             t('operations.continue.description');
51138     };
51139
51140
51141     operation.id = 'continue';
51142     operation.keys = [t('operations.continue.key')];
51143     operation.title = t('operations.continue.title');
51144
51145
51146     return operation;
51147 }
51148
51149 function operationDelete(selectedIDs, context) {
51150     var action = actionDeleteMultiple(selectedIDs);
51151
51152     var operation = function() {
51153         var annotation,
51154             nextSelectedID;
51155
51156         if (selectedIDs.length > 1) {
51157             annotation = t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51158
51159         } else {
51160             var id = selectedIDs[0],
51161                 entity = context.entity(id),
51162                 geometry = context.geometry(id),
51163                 parents = context.graph().parentWays(entity),
51164                 parent = parents[0];
51165
51166             annotation = t('operations.delete.annotation.' + geometry);
51167
51168             // Select the next closest node in the way.
51169             if (geometry === 'vertex' && parents.length === 1 && parent.nodes.length > 2) {
51170                 var nodes = parent.nodes,
51171                     i = nodes.indexOf(id);
51172
51173                 if (i === 0) {
51174                     i++;
51175                 } else if (i === nodes.length - 1) {
51176                     i--;
51177                 } else {
51178                     var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51179                         b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51180                     i = a < b ? i - 1 : i + 1;
51181                 }
51182
51183                 nextSelectedID = nodes[i];
51184             }
51185         }
51186
51187         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51188             context.enter(modeSelect(context, [nextSelectedID]));
51189         } else {
51190             context.enter(modeBrowse$$1(context));
51191         }
51192
51193         context.perform(action, annotation);
51194     };
51195
51196
51197     operation.available = function() {
51198         return true;
51199     };
51200
51201
51202     operation.disabled = function() {
51203         var reason;
51204         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51205             reason = 'connected_to_hidden';
51206         }
51207         return action.disabled(context.graph()) || reason;
51208     };
51209
51210
51211     operation.tooltip = function() {
51212         var disable = operation.disabled();
51213         return disable ?
51214             t('operations.delete.' + disable) :
51215             t('operations.delete.description');
51216     };
51217
51218
51219     operation.id = 'delete';
51220     operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51221     operation.title = t('operations.delete.title');
51222
51223
51224     return operation;
51225 }
51226
51227 function operationDisconnect(selectedIDs, context) {
51228     var vertices = lodash.filter(selectedIDs, function(entityId) {
51229         return context.geometry(entityId) === 'vertex';
51230     });
51231
51232     var entityId = vertices[0],
51233         action = actionDisconnect(entityId);
51234
51235     if (selectedIDs.length > 1) {
51236         action.limitWays(lodash.without(selectedIDs, entityId));
51237     }
51238
51239     var operation = function() {
51240         context.perform(action, t('operations.disconnect.annotation'));
51241     };
51242
51243
51244     operation.available = function() {
51245         return vertices.length === 1;
51246     };
51247
51248
51249     operation.disabled = function() {
51250         var reason;
51251         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51252             reason = 'connected_to_hidden';
51253         }
51254         return action.disabled(context.graph()) || reason;
51255     };
51256
51257
51258     operation.tooltip = function() {
51259         var disable = operation.disabled();
51260         return disable ?
51261             t('operations.disconnect.' + disable) :
51262             t('operations.disconnect.description');
51263     };
51264
51265
51266     operation.id = 'disconnect';
51267     operation.keys = [t('operations.disconnect.key')];
51268     operation.title = t('operations.disconnect.title');
51269
51270
51271     return operation;
51272 }
51273
51274 function operationMerge(selectedIDs, context) {
51275     var join = actionJoin(selectedIDs),
51276         merge = actionMerge(selectedIDs),
51277         mergePolygon = actionMergePolygon(selectedIDs);
51278
51279     var operation = function() {
51280         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
51281             action;
51282
51283         if (!join.disabled(context.graph())) {
51284             action = join;
51285         } else if (!merge.disabled(context.graph())) {
51286             action = merge;
51287         } else {
51288             action = mergePolygon;
51289         }
51290
51291         context.perform(action, annotation);
51292         var ids = selectedIDs.filter(function(id) { return context.hasEntity(id); });
51293         context.enter(modeSelect(context, ids).suppressMenu(true));
51294     };
51295
51296
51297     operation.available = function() {
51298         return selectedIDs.length >= 2;
51299     };
51300
51301
51302     operation.disabled = function() {
51303         return join.disabled(context.graph()) &&
51304             merge.disabled(context.graph()) &&
51305             mergePolygon.disabled(context.graph());
51306     };
51307
51308
51309     operation.tooltip = function() {
51310         var j = join.disabled(context.graph()),
51311             m = merge.disabled(context.graph()),
51312             p = mergePolygon.disabled(context.graph());
51313
51314         if (j === 'restriction' && m && p) {
51315             return t('operations.merge.restriction',
51316                 { relation: context.presets().item('type/restriction').name() });
51317         }
51318
51319         if (p === 'incomplete_relation' && j && m) {
51320             return t('operations.merge.incomplete_relation');
51321         }
51322
51323         if (j && m && p) {
51324             return t('operations.merge.' + j);
51325         }
51326
51327         return t('operations.merge.description');
51328     };
51329
51330
51331     operation.id = 'merge';
51332     operation.keys = [t('operations.merge.key')];
51333     operation.title = t('operations.merge.title');
51334
51335
51336     return operation;
51337 }
51338
51339 function operationMove(selectedIDs, context) {
51340     var extent = selectedIDs.reduce(function(extent, id) {
51341             return extent.extend(context.entity(id).extent(context.graph()));
51342         }, geoExtent$$1());
51343
51344     var operation = function() {
51345         context.enter(modeMove$$1(context, selectedIDs));
51346     };
51347
51348
51349     operation.available = function() {
51350         return selectedIDs.length > 1 ||
51351             context.entity(selectedIDs[0]).type !== 'node';
51352     };
51353
51354
51355     operation.disabled = function() {
51356         var reason;
51357         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51358             reason = 'too_large';
51359         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51360             reason = 'connected_to_hidden';
51361         }
51362
51363         return actionMove(selectedIDs).disabled(context.graph()) || reason;
51364     };
51365
51366
51367     operation.tooltip = function() {
51368         var disable = operation.disabled();
51369         return disable ?
51370             t('operations.move.' + disable) :
51371             t('operations.move.description');
51372     };
51373
51374
51375     operation.id = 'move';
51376     operation.keys = [t('operations.move.key')];
51377     operation.title = t('operations.move.title');
51378
51379
51380     return operation;
51381 }
51382
51383 function operationOrthogonalize(selectedIDs, context) {
51384     var entityId = selectedIDs[0],
51385         entity = context.entity(entityId),
51386         extent = entity.extent(context.graph()),
51387         geometry = context.geometry(entityId),
51388         action = actionOrthogonalize(entityId, context.projection);
51389
51390     var operation = function() {
51391         var annotation = t('operations.orthogonalize.annotation.' + geometry);
51392         context.perform(action, annotation);
51393     };
51394
51395
51396     operation.available = function() {
51397         return selectedIDs.length === 1 &&
51398             entity.type === 'way' &&
51399             entity.isClosed() &&
51400             lodash.uniq(entity.nodes).length > 2;
51401     };
51402
51403
51404     operation.disabled = function() {
51405         var reason;
51406         if (extent.percentContainedIn(context.extent()) < 0.8) {
51407             reason = 'too_large';
51408         } else if (context.hasHiddenConnections(entityId)) {
51409             reason = 'connected_to_hidden';
51410         }
51411         return action.disabled(context.graph()) || reason;
51412     };
51413
51414
51415     operation.tooltip = function() {
51416         var disable = operation.disabled();
51417         return disable ?
51418             t('operations.orthogonalize.' + disable) :
51419             t('operations.orthogonalize.description.' + geometry);
51420     };
51421
51422
51423     operation.id = 'orthogonalize';
51424     operation.keys = [t('operations.orthogonalize.key')];
51425     operation.title = t('operations.orthogonalize.title');
51426
51427
51428     return operation;
51429 }
51430
51431 function operationReverse(selectedIDs, context) {
51432     var entityId = selectedIDs[0];
51433
51434     var operation = function() {
51435         context.perform(
51436             actionReverse(entityId),
51437             t('operations.reverse.annotation')
51438         );
51439     };
51440
51441
51442     operation.available = function() {
51443         return selectedIDs.length === 1 &&
51444             context.geometry(entityId) === 'line';
51445     };
51446
51447
51448     operation.disabled = function() {
51449         return false;
51450     };
51451
51452
51453     operation.tooltip = function() {
51454         return t('operations.reverse.description');
51455     };
51456
51457
51458     operation.id = 'reverse';
51459     operation.keys = [t('operations.reverse.key')];
51460     operation.title = t('operations.reverse.title');
51461
51462
51463     return operation;
51464 }
51465
51466 function operationRotate(selectedIDs, context) {
51467     var entityId = selectedIDs[0],
51468         entity = context.entity(entityId),
51469         extent = entity.extent(context.graph()),
51470         geometry = context.geometry(entityId);
51471
51472     var operation = function() {
51473         context.enter(modeRotateWay$$1(context, entityId));
51474     };
51475
51476
51477     operation.available = function() {
51478         if (selectedIDs.length !== 1 || entity.type !== 'way')
51479             return false;
51480         if (geometry === 'area')
51481             return true;
51482         if (entity.isClosed() &&
51483             context.graph().parentRelations(entity).some(function(r) { return r.isMultipolygon(); }))
51484             return true;
51485         return false;
51486     };
51487
51488
51489     operation.disabled = function() {
51490         if (extent.percentContainedIn(context.extent()) < 0.8) {
51491             return 'too_large';
51492         } else if (context.hasHiddenConnections(entityId)) {
51493             return 'connected_to_hidden';
51494         } else {
51495             return false;
51496         }
51497     };
51498
51499
51500     operation.tooltip = function() {
51501         var disable = operation.disabled();
51502         return disable ?
51503             t('operations.rotate.' + disable) :
51504             t('operations.rotate.description');
51505     };
51506
51507
51508     operation.id = 'rotate';
51509     operation.keys = [t('operations.rotate.key')];
51510     operation.title = t('operations.rotate.title');
51511
51512
51513     return operation;
51514 }
51515
51516 function operationSplit(selectedIDs, context) {
51517     var vertices = lodash.filter(selectedIDs, function(entityId) {
51518         return context.geometry(entityId) === 'vertex';
51519     });
51520
51521     var entityId = vertices[0],
51522         action = actionSplit(entityId);
51523
51524     if (selectedIDs.length > 1) {
51525         action.limitWays(lodash.without(selectedIDs, entityId));
51526     }
51527
51528
51529     var operation = function() {
51530         var annotation;
51531
51532         var ways = action.ways(context.graph());
51533         if (ways.length === 1) {
51534             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
51535         } else {
51536             annotation = t('operations.split.annotation.multiple', {n: ways.length});
51537         }
51538
51539         var difference = context.perform(action, annotation);
51540         context.enter(modeSelect(context, difference.extantIDs()));
51541     };
51542
51543
51544     operation.available = function() {
51545         return vertices.length === 1;
51546     };
51547
51548
51549     operation.disabled = function() {
51550         var reason;
51551         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51552             reason = 'connected_to_hidden';
51553         }
51554         return action.disabled(context.graph()) || reason;
51555     };
51556
51557
51558     operation.tooltip = function() {
51559         var disable = operation.disabled();
51560         if (disable) {
51561             return t('operations.split.' + disable);
51562         }
51563
51564         var ways = action.ways(context.graph());
51565         if (ways.length === 1) {
51566             return t('operations.split.description.' + context.geometry(ways[0].id));
51567         } else {
51568             return t('operations.split.description.multiple');
51569         }
51570     };
51571
51572
51573     operation.id = 'split';
51574     operation.keys = [t('operations.split.key')];
51575     operation.title = t('operations.split.title');
51576
51577
51578     return operation;
51579 }
51580
51581 function operationStraighten(selectedIDs, context) {
51582     var entityId = selectedIDs[0],
51583         action = actionStraighten(entityId, context.projection);
51584
51585
51586     function operation() {
51587         var annotation = t('operations.straighten.annotation');
51588         context.perform(action, annotation);
51589     }
51590
51591
51592     operation.available = function() {
51593         var entity = context.entity(entityId);
51594         return selectedIDs.length === 1 &&
51595             entity.type === 'way' &&
51596             !entity.isClosed() &&
51597             lodash.uniq(entity.nodes).length > 2;
51598     };
51599
51600
51601     operation.disabled = function() {
51602         var reason;
51603         if (context.hasHiddenConnections(entityId)) {
51604             reason = 'connected_to_hidden';
51605         }
51606         return action.disabled(context.graph()) || reason;
51607     };
51608
51609
51610     operation.tooltip = function() {
51611         var disable = operation.disabled();
51612         return disable ?
51613             t('operations.straighten.' + disable) :
51614             t('operations.straighten.description');
51615     };
51616
51617
51618     operation.id = 'straighten';
51619     operation.keys = [t('operations.straighten.key')];
51620     operation.title = t('operations.straighten.title');
51621
51622
51623     return operation;
51624 }
51625
51626
51627
51628 var Operations = Object.freeze({
51629         operationCircularize: operationCircularize,
51630         operationContinue: operationContinue,
51631         operationDelete: operationDelete,
51632         operationDisconnect: operationDisconnect,
51633         operationMerge: operationMerge,
51634         operationMove: operationMove,
51635         operationOrthogonalize: operationOrthogonalize,
51636         operationReverse: operationReverse,
51637         operationRotate: operationRotate,
51638         operationSplit: operationSplit,
51639         operationStraighten: operationStraighten
51640 });
51641
51642 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
51643 // For example, ⌘Z -> Ctrl+Z
51644 function uiCmd(code) {
51645     var detected = utilDetect();
51646
51647     if (detected.os === 'mac') {
51648         return code;
51649     }
51650
51651     if (detected.os === 'win') {
51652         if (code === '⌘⇧Z') return 'Ctrl+Y';
51653     }
51654
51655     var result = '',
51656         replacements = {
51657             '⌘': 'Ctrl',
51658             '⇧': 'Shift',
51659             '⌥': 'Alt',
51660             '⌫': 'Backspace',
51661             '⌦': 'Delete'
51662         };
51663
51664     for (var i = 0; i < code.length; i++) {
51665         if (code[i] in replacements) {
51666             result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
51667         } else {
51668             result += code[i];
51669         }
51670     }
51671
51672     return result;
51673 }
51674
51675 var relatedParent;
51676
51677
51678 function modeSelect(context, selectedIDs) {
51679     var mode = {
51680         id: 'select',
51681         button: 'browse'
51682     };
51683
51684     var keybinding = d3keybinding('select'),
51685         timeout$$1 = null,
51686         behaviors = [
51687             behaviorCopy(context),
51688             behaviorPaste(context),
51689             behaviorBreathe(context),
51690             behaviorHover(context),
51691             behaviorSelect(context),
51692             behaviorLasso(context),
51693             modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
51694         ],
51695         inspector,
51696         radialMenu,
51697         newFeature = false,
51698         suppressMenu = false,
51699         follow = false;
51700
51701
51702     var wrap = context.container()
51703         .select('.inspector-wrap');
51704
51705
51706     function singular() {
51707         if (selectedIDs.length === 1) {
51708             return context.hasEntity(selectedIDs[0]);
51709         }
51710     }
51711
51712
51713     // find the common parent ways for nextVertex, previousVertex
51714     function commonParents() {
51715         var graph = context.graph(),
51716             commonParents = [];
51717
51718         for (var i = 0; i < selectedIDs.length; i++) {
51719             var entity = context.hasEntity(selectedIDs[i]);
51720             if (!entity || entity.geometry(graph) !== 'vertex') {
51721                 return [];  // selection includes some not vertexes
51722             }
51723
51724             var currParents = lodash.map(graph.parentWays(entity), 'id');
51725             if (!commonParents.length) {
51726                 commonParents = currParents;
51727                 continue;
51728             }
51729
51730             commonParents = lodash.intersection(commonParents, currParents);
51731             if (!commonParents.length) {
51732                 return [];
51733             }
51734         }
51735
51736         return commonParents;
51737     }
51738
51739
51740     function singularParent() {
51741         var parents = commonParents();
51742         if (!parents) {
51743             relatedParent = null;
51744             return null;
51745         }
51746
51747         // relatedParent is used when we visit a vertex with multiple
51748         // parents, and we want to remember which parent line we started on.
51749
51750         if (parents.length === 1) {
51751             relatedParent = parents[0];  // remember this parent for later
51752             return relatedParent;
51753         }
51754
51755         if (parents.indexOf(relatedParent) !== -1) {
51756             return relatedParent;   // prefer the previously seen parent
51757         }
51758
51759         return parents[0];
51760     }
51761
51762
51763     function closeMenu() {
51764         if (radialMenu) {
51765             context.surface().call(radialMenu.close);
51766         }
51767     }
51768
51769
51770     function positionMenu() {
51771         if (suppressMenu || !radialMenu) { return; }
51772
51773         var entity = singular();
51774         if (entity && context.geometry(entity.id) === 'relation') {
51775             suppressMenu = true;
51776         } else if (entity && entity.type === 'node') {
51777             radialMenu.center(context.projection(entity.loc));
51778         } else {
51779             var point = context.mouse(),
51780                 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
51781             if (geoPointInPolygon(point, viewport)) {
51782                 radialMenu.center(point);
51783             } else {
51784                 suppressMenu = true;
51785             }
51786         }
51787     }
51788
51789
51790     function showMenu() {
51791         closeMenu();
51792         if (!suppressMenu && radialMenu) {
51793             context.surface().call(radialMenu);
51794         }
51795     }
51796
51797
51798     function toggleMenu() {
51799         if (select('.radial-menu').empty()) {
51800             showMenu();
51801         } else {
51802             closeMenu();
51803         }
51804     }
51805
51806
51807     mode.selectedIDs = function() {
51808         return selectedIDs;
51809     };
51810
51811
51812     mode.reselect = function() {
51813         var surfaceNode = context.surface().node();
51814         if (surfaceNode.focus) {   // FF doesn't support it
51815             surfaceNode.focus();
51816         }
51817
51818         positionMenu();
51819         showMenu();
51820     };
51821
51822
51823     mode.newFeature = function(_) {
51824         if (!arguments.length) return newFeature;
51825         newFeature = _;
51826         return mode;
51827     };
51828
51829
51830     mode.suppressMenu = function(_) {
51831         if (!arguments.length) return suppressMenu;
51832         suppressMenu = _;
51833         return mode;
51834     };
51835
51836
51837     mode.follow = function(_) {
51838         if (!arguments.length) return follow;
51839         follow = _;
51840         return mode;
51841     };
51842
51843
51844     mode.enter = function() {
51845
51846         function update() {
51847             closeMenu();
51848             if (lodash.some(selectedIDs, function(id) { return !context.hasEntity(id); })) {
51849                 // Exit mode if selected entity gets undone
51850                 context.enter(modeBrowse$$1(context));
51851             }
51852         }
51853
51854
51855         function dblclick() {
51856             var target = select(event.target),
51857                 datum = target.datum();
51858
51859             if (datum instanceof osmWay && !target.classed('fill')) {
51860                 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
51861                     node = osmNode();
51862
51863                 var prev = datum.nodes[choice.index - 1],
51864                     next = datum.nodes[choice.index];
51865
51866                 context.perform(
51867                     actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, node),
51868                     t('operations.add.annotation.vertex')
51869                 );
51870
51871                 event.preventDefault();
51872                 event.stopPropagation();
51873             }
51874         }
51875
51876
51877         function selectElements(drawn) {
51878             var surface = context.surface(),
51879                 entity = singular();
51880
51881             if (entity && context.geometry(entity.id) === 'relation') {
51882                 suppressMenu = true;
51883                 return;
51884             }
51885
51886             surface.selectAll('.related')
51887                 .classed('related', false);
51888
51889             singularParent();
51890             if (relatedParent) {
51891                 surface.selectAll(utilEntitySelector([relatedParent]))
51892                     .classed('related', true);
51893             }
51894
51895             var selection$$1 = context.surface()
51896                 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
51897
51898             if (selection$$1.empty()) {
51899                 // Return to browse mode if selected DOM elements have
51900                 // disappeared because the user moved them out of view..
51901                 var source = event && event.type === 'zoom' && event.sourceEvent;
51902                 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
51903                     context.enter(modeBrowse$$1(context));
51904                 }
51905             } else {
51906                 selection$$1
51907                     .classed('selected', true);
51908             }
51909         }
51910
51911
51912         function esc() {
51913             if (!context.inIntro()) {
51914                 context.enter(modeBrowse$$1(context));
51915             }
51916         }
51917
51918
51919         function firstVertex() {
51920             event.preventDefault();
51921             var parent = singularParent();
51922             if (parent) {
51923                 var way = context.entity(parent);
51924                 context.enter(
51925                     modeSelect(context, [way.first()]).follow(true)
51926                 );
51927             }
51928         }
51929
51930
51931         function lastVertex() {
51932             event.preventDefault();
51933             var parent = singularParent();
51934             if (parent) {
51935                 var way = context.entity(parent);
51936                 context.enter(
51937                     modeSelect(context, [way.last()]).follow(true)
51938                 );
51939             }
51940         }
51941
51942
51943         function previousVertex() {
51944             event.preventDefault();
51945             var parent = singularParent();
51946             if (!parent) return;
51947
51948             var way = context.entity(parent),
51949                 length = way.nodes.length,
51950                 curr = way.nodes.indexOf(selectedIDs[0]),
51951                 index = -1;
51952
51953             if (curr > 0) {
51954                 index = curr - 1;
51955             } else if (way.isClosed()) {
51956                 index = length - 2;
51957             }
51958
51959             if (index !== -1) {
51960                 context.enter(
51961                     modeSelect(context, [way.nodes[index]]).follow(true)
51962                 );
51963             }
51964         }
51965
51966
51967         function nextVertex() {
51968             event.preventDefault();
51969             var parent = singularParent();
51970             if (!parent) return;
51971
51972             var way = context.entity(parent),
51973                 length = way.nodes.length,
51974                 curr = way.nodes.indexOf(selectedIDs[0]),
51975                 index = -1;
51976
51977             if (curr < length - 1) {
51978                 index = curr + 1;
51979             } else if (way.isClosed()) {
51980                 index = 0;
51981             }
51982
51983             if (index !== -1) {
51984                 context.enter(
51985                     modeSelect(context, [way.nodes[index]]).follow(true)
51986                 );
51987             }
51988         }
51989
51990
51991         function nextParent() {
51992             event.preventDefault();
51993             var parents = lodash.uniq(commonParents());
51994             if (!parents || parents.length < 2) return;
51995
51996             var index = parents.indexOf(relatedParent);
51997             if (index < 0 || index > parents.length - 2) {
51998                 relatedParent = parents[0];
51999             } else {
52000                 relatedParent = parents[index + 1];
52001             }
52002
52003             var surface = context.surface();
52004             surface.selectAll('.related')
52005                 .classed('related', false);
52006
52007             if (relatedParent) {
52008                 surface.selectAll(utilEntitySelector([relatedParent]))
52009                     .classed('related', true);
52010             }
52011         }
52012
52013
52014         behaviors.forEach(function(behavior) {
52015             context.install(behavior);
52016         });
52017
52018         var operations = lodash.without(values(Operations), operationDelete)
52019                 .map(function(o) { return o(selectedIDs, context); })
52020                 .filter(function(o) { return o.available(); });
52021
52022         operations.unshift(operationDelete(selectedIDs, context));
52023
52024         keybinding
52025             .on(['[','pgup'], previousVertex)
52026             .on([']', 'pgdown'], nextVertex)
52027             .on([uiCmd('⌘['), 'home'], firstVertex)
52028             .on([uiCmd('⌘]'), 'end'], lastVertex)
52029             .on(['\\', 'pause'], nextParent)
52030             .on('⎋', esc, true)
52031             .on('space', toggleMenu);
52032
52033         operations.forEach(function(operation) {
52034             operation.keys.forEach(function(key) {
52035                 keybinding.on(key, function() {
52036                     if (!(context.inIntro() || operation.disabled())) {
52037                         operation();
52038                     }
52039                 });
52040             });
52041         });
52042
52043         select(document)
52044             .call(keybinding);
52045
52046         radialMenu = uiRadialMenu(context, operations);
52047
52048         context.ui().sidebar
52049             .select(singular() ? singular().id : null, newFeature);
52050
52051         context.history()
52052             .on('undone.select', update)
52053             .on('redone.select', update);
52054
52055         context.map()
52056             .on('move.select', closeMenu)
52057             .on('drawn.select', selectElements);
52058
52059         selectElements();
52060
52061         var show = event && !suppressMenu;
52062
52063         if (show) {
52064             positionMenu();
52065         }
52066
52067         if (follow) {
52068             var extent$$1 = geoExtent$$1(),
52069                 graph = context.graph();
52070             selectedIDs.forEach(function(id) {
52071                 var entity = context.entity(id);
52072                 extent$$1._extend(entity.extent(graph));
52073             });
52074
52075             var loc = extent$$1.center();
52076             context.map().centerEase(loc);
52077         }
52078
52079         timeout$$1 = window.setTimeout(function() {
52080             if (show) {
52081                 showMenu();
52082             }
52083
52084             context.surface()
52085                 .on('dblclick.select', dblclick);
52086         }, 200);
52087
52088         if (selectedIDs.length > 1) {
52089             var entities = uiSelectionList(context, selectedIDs);
52090             context.ui().sidebar.show(entities);
52091         }
52092     };
52093
52094
52095     mode.exit = function() {
52096         if (timeout$$1) window.clearTimeout(timeout$$1);
52097
52098         if (inspector) wrap.call(inspector.close);
52099
52100         behaviors.forEach(function(behavior) {
52101             context.uninstall(behavior);
52102         });
52103
52104         keybinding.off();
52105         closeMenu();
52106         radialMenu = undefined;
52107
52108         context.history()
52109             .on('undone.select', null)
52110             .on('redone.select', null);
52111
52112         var surface = context.surface();
52113
52114         surface
52115             .on('dblclick.select', null);
52116
52117         surface
52118             .selectAll('.selected')
52119             .classed('selected', false);
52120
52121         surface
52122             .selectAll('.related')
52123             .classed('related', false);
52124
52125         context.map().on('drawn.select', null);
52126         context.ui().sidebar.hide();
52127     };
52128
52129
52130     return mode;
52131 }
52132
52133 function uiAccount(context) {
52134     var connection = context.connection();
52135
52136
52137     function update(selection$$1) {
52138         if (!connection.authenticated()) {
52139             selection$$1.selectAll('#userLink, #logoutLink')
52140                 .classed('hide', true);
52141             return;
52142         }
52143
52144         connection.userDetails(function(err, details) {
52145             var userLink = selection$$1.select('#userLink'),
52146                 logoutLink = selection$$1.select('#logoutLink');
52147
52148             userLink.html('');
52149             logoutLink.html('');
52150
52151             if (err) return;
52152
52153             selection$$1.selectAll('#userLink, #logoutLink')
52154                 .classed('hide', false);
52155
52156             // Link
52157             userLink.append('a')
52158                 .attr('href', connection.userURL(details.display_name))
52159                 .attr('target', '_blank');
52160
52161             // Add thumbnail or dont
52162             if (details.image_url) {
52163                 userLink.append('img')
52164                     .attr('class', 'icon pre-text user-icon')
52165                     .attr('src', details.image_url);
52166             } else {
52167                 userLink
52168                     .call(svgIcon('#icon-avatar', 'pre-text light'));
52169             }
52170
52171             // Add user name
52172             userLink.append('span')
52173                 .attr('class', 'label')
52174                 .text(details.display_name);
52175
52176             logoutLink.append('a')
52177                 .attr('class', 'logout')
52178                 .attr('href', '#')
52179                 .text(t('logout'))
52180                 .on('click.logout', function() {
52181                     event.preventDefault();
52182                     connection.logout();
52183                 });
52184         });
52185     }
52186
52187
52188     return function(selection$$1) {
52189         selection$$1.append('li')
52190             .attr('id', 'logoutLink')
52191             .classed('hide', true);
52192
52193         selection$$1.append('li')
52194             .attr('id', 'userLink')
52195             .classed('hide', true);
52196
52197         connection
52198             .on('change.account', function() { update(selection$$1); });
52199
52200         update(selection$$1);
52201     };
52202 }
52203
52204 function uiAttribution(context) {
52205     var selection$$1;
52206
52207
52208     function attribution(data, klass) {
52209         var div = selection$$1.selectAll('.' + klass)
52210             .data([0]);
52211
52212         div = div.enter()
52213             .append('div')
52214             .attr('class', klass)
52215             .merge(div);
52216
52217
52218         var background = div.selectAll('.attribution')
52219             .data(data, function(d) { return d.name(); });
52220
52221         background.exit()
52222             .remove();
52223
52224         background = background.enter()
52225             .append('span')
52226             .attr('class', 'attribution')
52227             .each(function(d) {
52228                 if (d.terms_html) {
52229                     select(this)
52230                         .html(d.terms_html);
52231                     return;
52232                 }
52233
52234                 var source = d.terms_text || d.id || d.name();
52235
52236                 if (d.logo) {
52237                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
52238                 }
52239
52240                 if (d.terms_url) {
52241                     select(this)
52242                         .append('a')
52243                         .attr('href', d.terms_url)
52244                         .attr('target', '_blank')
52245                         .html(source);
52246                 } else {
52247                     select(this)
52248                         .text(source);
52249                 }
52250             })
52251             .merge(background);
52252
52253
52254         var copyright = background.selectAll('.copyright-notice')
52255             .data(function(d) {
52256                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
52257                 return notice ? [notice] : [];
52258             });
52259
52260         copyright.exit()
52261             .remove();
52262
52263         copyright = copyright.enter()
52264             .append('span')
52265             .attr('class', 'copyright-notice')
52266             .merge(copyright);
52267
52268         copyright
52269             .text(String);
52270     }
52271
52272
52273     function update() {
52274         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
52275         attribution(context.background().overlayLayerSources().filter(function (s) {
52276             return s.validZoom(context.map().zoom());
52277         }), 'overlay-layer-attribution');
52278     }
52279
52280
52281     return function(select$$1) {
52282         selection$$1 = select$$1;
52283
52284         context.background()
52285             .on('change.attribution', update);
52286
52287         context.map()
52288             .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
52289
52290         update();
52291     };
52292 }
52293
52294 function rendererBackgroundSource(data) {
52295     var source = lodash.clone(data),
52296         offset = [0, 0],
52297         name = source.name,
52298         best = !!source.best;
52299
52300     source.scaleExtent = data.scaleExtent || [0, 20];
52301     source.overzoom = data.overzoom !== false;
52302
52303
52304     source.offset = function(_) {
52305         if (!arguments.length) return offset;
52306         offset = _;
52307         return source;
52308     };
52309
52310
52311     source.nudge = function(_, zoomlevel) {
52312         offset[0] += _[0] / Math.pow(2, zoomlevel);
52313         offset[1] += _[1] / Math.pow(2, zoomlevel);
52314         return source;
52315     };
52316
52317
52318     source.name = function() {
52319         return name;
52320     };
52321
52322
52323     source.best = function() {
52324         return best;
52325     };
52326
52327
52328     source.area = function() {
52329         if (!data.polygon) return Number.MAX_VALUE;  // worldwide
52330         var area$$1 = area$1({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
52331         return isNaN(area$$1) ? 0 : area$$1;
52332     };
52333
52334
52335     source.imageryUsed = function() {
52336         return name || source.id;
52337     };
52338
52339
52340     source.url = function(coord) {
52341         return data.template
52342             .replace('{x}', coord[0])
52343             .replace('{y}', coord[1])
52344             // TMS-flipped y coordinate
52345             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
52346             .replace(/\{z(oom)?\}/, coord[2])
52347             .replace(/\{switch:([^}]+)\}/, function(s, r) {
52348                 var subdomains = r.split(',');
52349                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
52350             })
52351             .replace('{u}', function() {
52352                 var u = '';
52353                 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
52354                     var b = 0;
52355                     var mask = 1 << (zoom$$1 - 1);
52356                     if ((coord[0] & mask) !== 0) b++;
52357                     if ((coord[1] & mask) !== 0) b += 2;
52358                     u += b.toString();
52359                 }
52360                 return u;
52361             });
52362     };
52363
52364
52365     source.intersects = function(extent$$1) {
52366         extent$$1 = extent$$1.polygon();
52367         return !data.polygon || data.polygon.some(function(polygon) {
52368             return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
52369         });
52370     };
52371
52372
52373     source.validZoom = function(z) {
52374         return source.scaleExtent[0] <= z &&
52375             (source.overzoom || source.scaleExtent[1] > z);
52376     };
52377
52378
52379     source.isLocatorOverlay = function() {
52380         return source.id === 'mapbox_locator_overlay';
52381     };
52382
52383
52384     source.copyrightNotices = function() {};
52385
52386
52387     return source;
52388 }
52389
52390
52391 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
52392     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
52393     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
52394
52395     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
52396
52397     var bing = rendererBackgroundSource(data),
52398         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
52399         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
52400             key + '&jsonp={callback}',
52401         providers = [];
52402
52403     jsonpRequest(url, function(json$$1) {
52404         providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
52405             return {
52406                 attribution: provider.attribution,
52407                 areas: provider.coverageAreas.map(function(area$$1) {
52408                     return {
52409                         zoom: [area$$1.zoomMin, area$$1.zoomMax],
52410                         extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
52411                     };
52412                 })
52413             };
52414         });
52415         dispatch$$1.call('change');
52416     });
52417
52418     bing.copyrightNotices = function(zoom$$1, extent$$1) {
52419         zoom$$1 = Math.min(zoom$$1, 21);
52420         return providers.filter(function(provider) {
52421             return lodash.some(provider.areas, function(area$$1) {
52422                 return extent$$1.intersects(area$$1.extent) &&
52423                     area$$1.zoom[0] <= zoom$$1 &&
52424                     area$$1.zoom[1] >= zoom$$1;
52425             });
52426         }).map(function(provider) {
52427             return provider.attribution;
52428         }).join(', ');
52429     };
52430
52431     bing.logo = 'bing_maps.png';
52432     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
52433
52434     return bing;
52435 };
52436
52437
52438 rendererBackgroundSource.None = function() {
52439     var source = rendererBackgroundSource({ id: 'none', template: '' });
52440
52441     source.name = function() {
52442         return t('background.none');
52443     };
52444
52445     source.imageryUsed = function() {
52446         return 'None';
52447     };
52448
52449     source.area = function() {
52450         return -1;  // sources in background pane are sorted by area
52451     };
52452
52453     return source;
52454 };
52455
52456
52457 rendererBackgroundSource.Custom = function(template) {
52458     var source = rendererBackgroundSource({ id: 'custom', template: template });
52459
52460     source.name = function() {
52461         return t('background.custom');
52462     };
52463
52464     source.imageryUsed = function() {
52465         return 'Custom (' + template + ')';
52466     };
52467
52468     source.area = function() {
52469         return -2;  // sources in background pane are sorted by area
52470     };
52471
52472     return source;
52473 };
52474
52475 function rendererTileLayer(context) {
52476     var tileSize = 256,
52477         tile = d3geoTile(),
52478         projection,
52479         cache = {},
52480         tileOrigin,
52481         z,
52482         transformProp = utilPrefixCSSProperty('Transform'),
52483         source = rendererBackgroundSource.None();
52484
52485
52486     // blacklist overlay tiles around Null Island..
52487     function nearNullIsland(x, y, z) {
52488         if (z >= 7) {
52489             var center = Math.pow(2, z - 1),
52490                 width = Math.pow(2, z - 6),
52491                 min$$1 = center - (width / 2),
52492                 max$$1 = center + (width / 2) - 1;
52493             return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
52494         }
52495         return false;
52496     }
52497
52498
52499     function tileSizeAtZoom(d, z) {
52500         var epsilon = 0.002;
52501         return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
52502     }
52503
52504
52505     function atZoom(t, distance) {
52506         var power = Math.pow(2, distance);
52507         return [
52508             Math.floor(t[0] * power),
52509             Math.floor(t[1] * power),
52510             t[2] + distance];
52511     }
52512
52513
52514     function lookUp(d) {
52515         for (var up = -1; up > -d[2]; up--) {
52516             var tile = atZoom(d, up);
52517             if (cache[source.url(tile)] !== false) {
52518                 return tile;
52519             }
52520         }
52521     }
52522
52523
52524     function uniqueBy(a, n) {
52525         var o = [], seen = {};
52526         for (var i = 0; i < a.length; i++) {
52527             if (seen[a[i][n]] === undefined) {
52528                 o.push(a[i]);
52529                 seen[a[i][n]] = true;
52530             }
52531         }
52532         return o;
52533     }
52534
52535
52536     function addSource(d) {
52537         d.push(source.url(d));
52538         return d;
52539     }
52540
52541
52542     // Update tiles based on current state of `projection`.
52543     function background(selection$$1) {
52544         tile.scale(projection.scale() * 2 * Math.PI)
52545             .translate(projection.translate());
52546
52547         tileOrigin = [
52548             projection.scale() * Math.PI - projection.translate()[0],
52549             projection.scale() * Math.PI - projection.translate()[1]];
52550
52551         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
52552
52553         render(selection$$1);
52554     }
52555
52556
52557     // Derive the tiles onscreen, remove those offscreen and position them.
52558     // Important that this part not depend on `projection` because it's
52559     // rentered when tiles load/error (see #644).
52560     function render(selection$$1) {
52561         var requests = [];
52562         var showDebug = context.getDebug('tile') && !source.overlay;
52563
52564         if (source.validZoom(z)) {
52565             tile().forEach(function(d) {
52566                 addSource(d);
52567                 if (d[3] === '') return;
52568                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
52569                 requests.push(d);
52570                 if (cache[d[3]] === false && lookUp(d)) {
52571                     requests.push(addSource(lookUp(d)));
52572                 }
52573             });
52574
52575             requests = uniqueBy(requests, 3).filter(function(r) {
52576                 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
52577                     return false;
52578                 }
52579                 // don't re-request tiles which have failed in the past
52580                 return cache[r[3]] !== false;
52581             });
52582         }
52583
52584         var pixelOffset = [
52585             source.offset()[0] * Math.pow(2, z),
52586             source.offset()[1] * Math.pow(2, z)
52587         ];
52588
52589         function load(d) {
52590             cache[d[3]] = true;
52591             select(this)
52592                 .on('error', null)
52593                 .on('load', null)
52594                 .classed('tile-loaded', true);
52595             render(selection$$1);
52596         }
52597
52598         function error(d) {
52599             cache[d[3]] = false;
52600             select(this)
52601                 .on('error', null)
52602                 .on('load', null)
52603                 .remove();
52604             render(selection$$1);
52605         }
52606
52607         function imageTransform(d) {
52608             var _ts = tileSize * Math.pow(2, z - d[2]);
52609             var scale = tileSizeAtZoom(d, z);
52610             return 'translate(' +
52611                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
52612                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
52613                 'scale(' + scale + ',' + scale + ')';
52614         }
52615
52616         function debugTransform(d) {
52617             var _ts = tileSize * Math.pow(2, z - d[2]);
52618             var scale = tileSizeAtZoom(d, z);
52619             return 'translate(' +
52620                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
52621                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
52622         }
52623
52624
52625         var image = selection$$1.selectAll('img')
52626             .data(requests, function(d) { return d[3]; });
52627
52628         image.exit()
52629             .style(transformProp, imageTransform)
52630             .classed('tile-removing', true)
52631             .each(function() {
52632                 var tile = select(this);
52633                 window.setTimeout(function() {
52634                     if (tile.classed('tile-removing')) {
52635                         tile.remove();
52636                     }
52637                 }, 300);
52638             });
52639
52640         image.enter()
52641           .append('img')
52642             .attr('class', 'tile')
52643             .attr('src', function(d) { return d[3]; })
52644             .on('error', error)
52645             .on('load', load)
52646           .merge(image)
52647             .style(transformProp, imageTransform)
52648             .classed('tile-debug', showDebug)
52649             .classed('tile-removing', false);
52650
52651
52652         var debug = selection$$1.selectAll('.tile-label-debug')
52653             .data(showDebug ? requests : [], function(d) { return d[3]; });
52654
52655         debug.exit()
52656             .remove();
52657
52658         debug.enter()
52659           .append('div')
52660             .attr('class', 'tile-label-debug')
52661           .merge(debug)
52662             .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
52663             .style(transformProp, debugTransform);
52664     }
52665
52666
52667     background.projection = function(_) {
52668         if (!arguments.length) return projection;
52669         projection = _;
52670         return background;
52671     };
52672
52673
52674     background.dimensions = function(_) {
52675         if (!arguments.length) return tile.size();
52676         tile.size(_);
52677         return background;
52678     };
52679
52680
52681     background.source = function(_) {
52682         if (!arguments.length) return source;
52683         source = _;
52684         cache = {};
52685         tile.scaleExtent(source.scaleExtent);
52686         return background;
52687     };
52688
52689
52690     return background;
52691 }
52692
52693 function rendererBackground(context) {
52694     var dispatch$$1 = dispatch('change'),
52695         baseLayer = rendererTileLayer(context).projection(context.projection),
52696         overlayLayers = [],
52697         backgroundSources;
52698
52699
52700     function findSource(id) {
52701         return lodash.find(backgroundSources, function(d) {
52702             return d.id && d.id === id;
52703         });
52704     }
52705
52706
52707     function background(selection$$1) {
52708         var base = selection$$1.selectAll('.layer-background')
52709             .data([0]);
52710
52711         base.enter()
52712             .insert('div', '.layer-data')
52713             .attr('class', 'layer layer-background')
52714             .merge(base)
52715             .call(baseLayer);
52716
52717         var overlays = selection$$1.selectAll('.layer-overlay')
52718             .data(overlayLayers, function(d) { return d.source().name(); });
52719
52720         overlays.exit()
52721             .remove();
52722
52723         overlays.enter()
52724             .insert('div', '.layer-data')
52725             .attr('class', 'layer layer-overlay')
52726             .merge(overlays)
52727             .each(function(layer) { select(this).call(layer); });
52728     }
52729
52730
52731     background.updateImagery = function() {
52732         var b = background.baseLayerSource(),
52733             o = overlayLayers
52734                 .filter(function (d) { return !d.source().isLocatorOverlay(); })
52735                 .map(function (d) { return d.source().id; })
52736                 .join(','),
52737             meters = geoOffsetToMeters(b.offset()),
52738             epsilon = 0.01,
52739             x = +meters[0].toFixed(2),
52740             y = +meters[1].toFixed(2),
52741             q = utilStringQs(window.location.hash.substring(1));
52742
52743         var id = b.id;
52744         if (id === 'custom') {
52745             id = 'custom:' + b.template;
52746         }
52747
52748         if (id) {
52749             q.background = id;
52750         } else {
52751             delete q.background;
52752         }
52753
52754         if (o) {
52755             q.overlays = o;
52756         } else {
52757             delete q.overlays;
52758         }
52759
52760         if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
52761             q.offset = x + ',' + y;
52762         } else {
52763             delete q.offset;
52764         }
52765
52766         window.location.replace('#' + utilQsString(q, true));
52767
52768         var imageryUsed = [b.imageryUsed()];
52769
52770         overlayLayers
52771             .filter(function (d) { return !d.source().isLocatorOverlay(); })
52772             .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
52773
52774         var gpx = context.layers().layer('gpx');
52775         if (gpx && gpx.enabled() && gpx.hasGpx()) {
52776             imageryUsed.push('Local GPX');
52777         }
52778
52779         var mapillary_images = context.layers().layer('mapillary-images');
52780         if (mapillary_images && mapillary_images.enabled()) {
52781             imageryUsed.push('Mapillary Images');
52782         }
52783
52784         var mapillary_signs = context.layers().layer('mapillary-signs');
52785         if (mapillary_signs && mapillary_signs.enabled()) {
52786             imageryUsed.push('Mapillary Signs');
52787         }
52788
52789         context.history().imageryUsed(imageryUsed);
52790     };
52791
52792
52793     background.sources = function(extent$$1) {
52794         return backgroundSources.filter(function(source) {
52795             return source.intersects(extent$$1);
52796         });
52797     };
52798
52799
52800     background.dimensions = function(_) {
52801         if (!_) return;
52802         baseLayer.dimensions(_);
52803
52804         overlayLayers.forEach(function(layer) {
52805             layer.dimensions(_);
52806         });
52807     };
52808
52809
52810     background.baseLayerSource = function(d) {
52811         if (!arguments.length) return baseLayer.source();
52812         baseLayer.source(d);
52813         dispatch$$1.call('change');
52814         background.updateImagery();
52815         return background;
52816     };
52817
52818
52819     background.bing = function() {
52820         background.baseLayerSource(findSource('Bing'));
52821     };
52822
52823
52824     background.showsLayer = function(d) {
52825         return d === baseLayer.source() ||
52826             (d.id === 'custom' && baseLayer.source().id === 'custom') ||
52827             overlayLayers.some(function(l) { return l.source() === d; });
52828     };
52829
52830
52831     background.overlayLayerSources = function() {
52832         return overlayLayers.map(function (l) { return l.source(); });
52833     };
52834
52835
52836     background.toggleOverlayLayer = function(d) {
52837         var layer;
52838
52839         for (var i = 0; i < overlayLayers.length; i++) {
52840             layer = overlayLayers[i];
52841             if (layer.source() === d) {
52842                 overlayLayers.splice(i, 1);
52843                 dispatch$$1.call('change');
52844                 background.updateImagery();
52845                 return;
52846             }
52847         }
52848
52849         layer = rendererTileLayer(context)
52850             .source(d)
52851             .projection(context.projection)
52852             .dimensions(baseLayer.dimensions());
52853
52854         overlayLayers.push(layer);
52855         dispatch$$1.call('change');
52856         background.updateImagery();
52857     };
52858
52859
52860     background.nudge = function(d, zoom$$1) {
52861         baseLayer.source().nudge(d, zoom$$1);
52862         dispatch$$1.call('change');
52863         background.updateImagery();
52864         return background;
52865     };
52866
52867
52868     background.offset = function(d) {
52869         if (!arguments.length) return baseLayer.source().offset();
52870         baseLayer.source().offset(d);
52871         dispatch$$1.call('change');
52872         background.updateImagery();
52873         return background;
52874     };
52875
52876
52877     background.init = function() {
52878         function parseMap(qmap) {
52879             if (!qmap) return false;
52880             var args = qmap.split('/').map(Number);
52881             if (args.length < 3 || args.some(isNaN)) return false;
52882             return geoExtent$$1([args[2], args[1]]);
52883         }
52884
52885         var dataImagery = data.imagery || [],
52886             q = utilStringQs(window.location.hash.substring(1)),
52887             chosen = q.background || q.layer,
52888             extent$$1 = parseMap(q.map),
52889             best;
52890
52891         backgroundSources = dataImagery.map(function(source) {
52892             if (source.type === 'bing') {
52893                 return rendererBackgroundSource.Bing(source, dispatch$$1);
52894             } else {
52895                 return rendererBackgroundSource(source);
52896             }
52897         });
52898
52899         backgroundSources.unshift(rendererBackgroundSource.None());
52900
52901         if (!chosen && extent$$1) {
52902             best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
52903         }
52904
52905         if (chosen && chosen.indexOf('custom:') === 0) {
52906             background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
52907         } else {
52908             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
52909         }
52910
52911         var locator = lodash.find(backgroundSources, function(d) {
52912             return d.overlay && d.default;
52913         });
52914
52915         if (locator) {
52916             background.toggleOverlayLayer(locator);
52917         }
52918
52919         var overlays = (q.overlays || '').split(',');
52920         overlays.forEach(function(overlay) {
52921             overlay = findSource(overlay);
52922             if (overlay) {
52923                 background.toggleOverlayLayer(overlay);
52924             }
52925         });
52926
52927         if (q.gpx) {
52928             var gpx = context.layers().layer('gpx');
52929             if (gpx) {
52930                 gpx.url(q.gpx);
52931             }
52932         }
52933
52934         if (q.offset) {
52935             var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
52936                 return !isNaN(n) && n;
52937             });
52938
52939             if (offset.length === 2) {
52940                 background.offset(geoMetersToOffset(offset));
52941             }
52942         }
52943     };
52944
52945
52946     return utilRebind(background, dispatch$$1, 'on');
52947 }
52948
52949 function rendererFeatures(context) {
52950     var traffic_roads = {
52951         'motorway': true,
52952         'motorway_link': true,
52953         'trunk': true,
52954         'trunk_link': true,
52955         'primary': true,
52956         'primary_link': true,
52957         'secondary': true,
52958         'secondary_link': true,
52959         'tertiary': true,
52960         'tertiary_link': true,
52961         'residential': true,
52962         'unclassified': true,
52963         'living_street': true
52964     };
52965
52966     var service_roads = {
52967         'service': true,
52968         'road': true,
52969         'track': true
52970     };
52971
52972     var paths = {
52973         'path': true,
52974         'footway': true,
52975         'cycleway': true,
52976         'bridleway': true,
52977         'steps': true,
52978         'pedestrian': true,
52979         'corridor': true
52980     };
52981
52982     var past_futures = {
52983         'proposed': true,
52984         'construction': true,
52985         'abandoned': true,
52986         'dismantled': true,
52987         'disused': true,
52988         'razed': true,
52989         'demolished': true,
52990         'obliterated': true
52991     };
52992
52993     var dispatch$$1 = dispatch('change', 'redraw'),
52994         _cullFactor = 1,
52995         _cache = {},
52996         _features = {},
52997         _stats = {},
52998         _keys = [],
52999         _hidden = [];
53000
53001
53002     function update() {
53003         _hidden = features.hidden();
53004         dispatch$$1.call('change');
53005         dispatch$$1.call('redraw');
53006     }
53007
53008
53009     function defineFeature(k, filter, max$$1) {
53010         _keys.push(k);
53011         _features[k] = {
53012             filter: filter,
53013             enabled: true,   // whether the user wants it enabled..
53014             count: 0,
53015             currentMax: (max$$1 || Infinity),
53016             defaultMax: (max$$1 || Infinity),
53017             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
53018             disable: function() { this.enabled = false; this.currentMax = 0; },
53019             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
53020             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
53021         };
53022     }
53023
53024
53025     defineFeature('points', function isPoint(entity, resolver, geometry) {
53026         return geometry === 'point';
53027     }, 200);
53028
53029     defineFeature('traffic_roads', function isTrafficRoad(entity) {
53030         return traffic_roads[entity.tags.highway];
53031     });
53032
53033     defineFeature('service_roads', function isServiceRoad(entity) {
53034         return service_roads[entity.tags.highway];
53035     });
53036
53037     defineFeature('paths', function isPath(entity) {
53038         return paths[entity.tags.highway];
53039     });
53040
53041     defineFeature('buildings', function isBuilding(entity) {
53042         return (
53043             !!entity.tags['building:part'] ||
53044             (!!entity.tags.building && entity.tags.building !== 'no') ||
53045             entity.tags.amenity === 'shelter' ||
53046             entity.tags.parking === 'multi-storey' ||
53047             entity.tags.parking === 'sheds' ||
53048             entity.tags.parking === 'carports' ||
53049             entity.tags.parking === 'garage_boxes'
53050         );
53051     }, 250);
53052
53053     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
53054         return geometry === 'area' &&
53055             !_features.buildings.filter(entity) &&
53056             !_features.water.filter(entity);
53057     });
53058
53059     defineFeature('boundaries', function isBoundary(entity) {
53060         return !!entity.tags.boundary;
53061     });
53062
53063     defineFeature('water', function isWater(entity) {
53064         return (
53065             !!entity.tags.waterway ||
53066             entity.tags.natural === 'water' ||
53067             entity.tags.natural === 'coastline' ||
53068             entity.tags.natural === 'bay' ||
53069             entity.tags.landuse === 'pond' ||
53070             entity.tags.landuse === 'basin' ||
53071             entity.tags.landuse === 'reservoir' ||
53072             entity.tags.landuse === 'salt_pond'
53073         );
53074     });
53075
53076     defineFeature('rail', function isRail(entity) {
53077         return (
53078             !!entity.tags.railway ||
53079             entity.tags.landuse === 'railway'
53080         ) && !(
53081             traffic_roads[entity.tags.highway] ||
53082             service_roads[entity.tags.highway] ||
53083             paths[entity.tags.highway]
53084         );
53085     });
53086
53087     defineFeature('power', function isPower(entity) {
53088         return !!entity.tags.power;
53089     });
53090
53091     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
53092     defineFeature('past_future', function isPastFuture(entity) {
53093         if (
53094             traffic_roads[entity.tags.highway] ||
53095             service_roads[entity.tags.highway] ||
53096             paths[entity.tags.highway]
53097         ) { return false; }
53098
53099         var strings = Object.keys(entity.tags);
53100
53101         for (var i = 0; i < strings.length; i++) {
53102             var s = strings[i];
53103             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
53104         }
53105         return false;
53106     });
53107
53108     // Lines or areas that don't match another feature filter.
53109     // IMPORTANT: The 'others' feature must be the last one defined,
53110     //   so that code in getMatches can skip this test if `hasMatch = true`
53111     defineFeature('others', function isOther(entity, resolver, geometry) {
53112         return (geometry === 'line' || geometry === 'area');
53113     });
53114
53115
53116     function features() {}
53117
53118
53119     features.features = function() {
53120         return _features;
53121     };
53122
53123
53124     features.keys = function() {
53125         return _keys;
53126     };
53127
53128
53129     features.enabled = function(k) {
53130         if (!arguments.length) {
53131             return _keys.filter(function(k) { return _features[k].enabled; });
53132         }
53133         return _features[k] && _features[k].enabled;
53134     };
53135
53136
53137     features.disabled = function(k) {
53138         if (!arguments.length) {
53139             return _keys.filter(function(k) { return !_features[k].enabled; });
53140         }
53141         return _features[k] && !_features[k].enabled;
53142     };
53143
53144
53145     features.hidden = function(k) {
53146         if (!arguments.length) {
53147             return _keys.filter(function(k) { return _features[k].hidden(); });
53148         }
53149         return _features[k] && _features[k].hidden();
53150     };
53151
53152
53153     features.autoHidden = function(k) {
53154         if (!arguments.length) {
53155             return _keys.filter(function(k) { return _features[k].autoHidden(); });
53156         }
53157         return _features[k] && _features[k].autoHidden();
53158     };
53159
53160
53161     features.enable = function(k) {
53162         if (_features[k] && !_features[k].enabled) {
53163             _features[k].enable();
53164             update();
53165         }
53166     };
53167
53168
53169     features.disable = function(k) {
53170         if (_features[k] && _features[k].enabled) {
53171             _features[k].disable();
53172             update();
53173         }
53174     };
53175
53176
53177     features.toggle = function(k) {
53178         if (_features[k]) {
53179             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
53180             update();
53181         }
53182     };
53183
53184
53185     features.resetStats = function() {
53186         for (var i = 0; i < _keys.length; i++) {
53187             _features[_keys[i]].count = 0;
53188         }
53189         dispatch$$1.call('change');
53190     };
53191
53192
53193     features.gatherStats = function(d, resolver, dimensions) {
53194         var needsRedraw = false,
53195             type = lodash.groupBy(d, function(ent) { return ent.type; }),
53196             entities = [].concat(type.relation || [], type.way || [], type.node || []),
53197             currHidden, geometry, matches, i, j;
53198
53199         for (i = 0; i < _keys.length; i++) {
53200             _features[_keys[i]].count = 0;
53201         }
53202
53203         // adjust the threshold for point/building culling based on viewport size..
53204         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
53205         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
53206
53207         for (i = 0; i < entities.length; i++) {
53208             geometry = entities[i].geometry(resolver);
53209             if (!(geometry === 'vertex' || geometry === 'relation')) {
53210                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
53211                 for (j = 0; j < matches.length; j++) {
53212                     _features[matches[j]].count++;
53213                 }
53214             }
53215         }
53216
53217         currHidden = features.hidden();
53218         if (currHidden !== _hidden) {
53219             _hidden = currHidden;
53220             needsRedraw = true;
53221             dispatch$$1.call('change');
53222         }
53223
53224         return needsRedraw;
53225     };
53226
53227
53228     features.stats = function() {
53229         for (var i = 0; i < _keys.length; i++) {
53230             _stats[_keys[i]] = _features[_keys[i]].count;
53231         }
53232
53233         return _stats;
53234     };
53235
53236
53237     features.clear = function(d) {
53238         for (var i = 0; i < d.length; i++) {
53239             features.clearEntity(d[i]);
53240         }
53241     };
53242
53243
53244     features.clearEntity = function(entity) {
53245         delete _cache[osmEntity$$1.key(entity)];
53246     };
53247
53248
53249     features.reset = function() {
53250         _cache = {};
53251     };
53252
53253
53254     features.getMatches = function(entity, resolver, geometry) {
53255         if (geometry === 'vertex' || geometry === 'relation') return {};
53256
53257         var ent = osmEntity$$1.key(entity);
53258         if (!_cache[ent]) {
53259             _cache[ent] = {};
53260         }
53261
53262         if (!_cache[ent].matches) {
53263             var matches = {},
53264                 hasMatch = false;
53265
53266             for (var i = 0; i < _keys.length; i++) {
53267                 if (_keys[i] === 'others') {
53268                     if (hasMatch) continue;
53269
53270                     // Multipolygon members:
53271                     // If an entity...
53272                     //   1. is a way that hasn't matched other 'interesting' feature rules,
53273                     //   2. and it belongs to a single parent multipolygon relation
53274                     // ...then match whatever feature rules the parent multipolygon has matched.
53275                     // see #2548, #2887
53276                     //
53277                     // IMPORTANT:
53278                     // For this to work, getMatches must be called on relations before ways.
53279                     //
53280                     if (entity.type === 'way') {
53281                         var parents = features.getParents(entity, resolver, geometry);
53282                         if (parents.length === 1 && parents[0].isMultipolygon()) {
53283                             var pkey = osmEntity$$1.key(parents[0]);
53284                             if (_cache[pkey] && _cache[pkey].matches) {
53285                                 matches = lodash.clone(_cache[pkey].matches);
53286                                 continue;
53287                             }
53288                         }
53289                     }
53290                 }
53291
53292                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
53293                     matches[_keys[i]] = hasMatch = true;
53294                 }
53295             }
53296             _cache[ent].matches = matches;
53297         }
53298
53299         return _cache[ent].matches;
53300     };
53301
53302
53303     features.getParents = function(entity, resolver, geometry) {
53304         if (geometry === 'point') return [];
53305
53306         var ent = osmEntity$$1.key(entity);
53307         if (!_cache[ent]) {
53308             _cache[ent] = {};
53309         }
53310
53311         if (!_cache[ent].parents) {
53312             var parents = [];
53313             if (geometry === 'vertex') {
53314                 parents = resolver.parentWays(entity);
53315             } else {   // 'line', 'area', 'relation'
53316                 parents = resolver.parentRelations(entity);
53317             }
53318             _cache[ent].parents = parents;
53319         }
53320         return _cache[ent].parents;
53321     };
53322
53323
53324     features.isHiddenFeature = function(entity, resolver, geometry) {
53325         if (!_hidden.length) return false;
53326         if (!entity.version) return false;
53327
53328         var matches = features.getMatches(entity, resolver, geometry);
53329
53330         for (var i = 0; i < _hidden.length; i++) {
53331             if (matches[_hidden[i]]) return true;
53332         }
53333         return false;
53334     };
53335
53336
53337     features.isHiddenChild = function(entity, resolver, geometry) {
53338         if (!_hidden.length) return false;
53339         if (!entity.version || geometry === 'point') return false;
53340
53341         var parents = features.getParents(entity, resolver, geometry);
53342         if (!parents.length) return false;
53343
53344         for (var i = 0; i < parents.length; i++) {
53345             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
53346                 return false;
53347             }
53348         }
53349         return true;
53350     };
53351
53352
53353     features.hasHiddenConnections = function(entity, resolver) {
53354         if (!_hidden.length) return false;
53355         var childNodes, connections;
53356
53357         if (entity.type === 'midpoint') {
53358             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
53359             connections = [];
53360         } else {
53361             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
53362             connections = features.getParents(entity, resolver, entity.geometry(resolver));
53363         }
53364
53365         // gather ways connected to child nodes..
53366         connections = lodash.reduce(childNodes, function(result, e) {
53367             return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
53368         }, connections);
53369
53370         return connections.length ? lodash.some(connections, function(e) {
53371             return features.isHidden(e, resolver, e.geometry(resolver));
53372         }) : false;
53373     };
53374
53375
53376     features.isHidden = function(entity, resolver, geometry) {
53377         if (!_hidden.length) return false;
53378         if (!entity.version) return false;
53379
53380         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
53381         return fn(entity, resolver, geometry);
53382     };
53383
53384
53385     features.filter = function(d, resolver) {
53386         if (!_hidden.length) return d;
53387
53388         var result = [];
53389         for (var i = 0; i < d.length; i++) {
53390             var entity = d[i];
53391             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
53392                 result.push(entity);
53393             }
53394         }
53395         return result;
53396     };
53397
53398
53399     return utilRebind(features, dispatch$$1, 'on');
53400 }
53401
53402 function utilBindOnce(target, type, listener, capture) {
53403     var typeOnce = type + '.once';
53404     function one() {
53405         target.on(typeOnce, null);
53406         listener.apply(this, arguments);
53407     }
53408     target.on(typeOnce, one, capture);
53409     return this;
53410 }
53411
53412 function rendererMap(context) {
53413
53414     var dimensions = [1, 1],
53415         dispatch$$1 = dispatch('move', 'drawn'),
53416         projection = context.projection,
53417         dblclickEnabled = true,
53418         redrawEnabled = true,
53419         transformStart = projection.transform(),
53420         transformed = false,
53421         minzoom = 0,
53422         drawLayers = svgLayers(projection, context),
53423         drawPoints = svgPoints$$1(projection, context),
53424         drawVertices = svgVertices$$1(projection, context),
53425         drawLines = svgLines$$1(projection),
53426         drawAreas = svgAreas$$1(projection, context),
53427         drawMidpoints = svgMidpoints$$1(projection, context),
53428         drawLabels = svgLabels(projection, context),
53429         supersurface,
53430         wrapper,
53431         surface,
53432         mouse$$1,
53433         mousemove;
53434
53435     var zoom$$1 = zoom()
53436             .scaleExtent([ztok(2), ztok(24)])   // TODO: uncomment interpolate when d3.zoom 1.0.4 avail:
53437             // .interpolate(d3.interpolate)     // https://github.com/d3/d3-zoom/issues/54
53438             .on('zoom', zoomPan);               // default zoom interpolator does a fly-out-in
53439
53440     var _selection = select(null);
53441
53442
53443     function map$$1(selection$$1) {
53444
53445         _selection = selection$$1;
53446
53447         context
53448             .on('change.map', immediateRedraw);
53449         context.connection()
53450             .on('change.map', immediateRedraw);
53451         context.history()
53452             .on('change.map', immediateRedraw);
53453         context.background()
53454             .on('change.map', immediateRedraw);
53455         context.features()
53456             .on('redraw.map', immediateRedraw);
53457         drawLayers
53458             .on('change.map', function() {
53459                 context.background().updateImagery();
53460                 immediateRedraw();
53461             });
53462
53463         selection$$1
53464             .on('dblclick.map', dblClick)
53465             .call(zoom$$1, projection.transform());
53466
53467         supersurface = selection$$1.append('div')
53468             .attr('id', 'supersurface')
53469             .call(utilSetTransform, 0, 0);
53470
53471         // Need a wrapper div because Opera can't cope with an absolutely positioned
53472         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
53473         wrapper = supersurface
53474             .append('div')
53475             .attr('class', 'layer layer-data');
53476
53477         map$$1.surface = surface = wrapper
53478             .call(drawLayers)
53479             .selectAll('.surface')
53480             .attr('id', 'surface');
53481
53482         surface
53483             .call(drawLabels.observe)
53484             .on('mousedown.zoom', function() {
53485                 if (event.button === 2) {
53486                     event.stopPropagation();
53487                 }
53488             }, true)
53489             .on('mouseup.zoom', function() {
53490                 if (resetTransform()) immediateRedraw();
53491             })
53492             .on('mousemove.map', function() {
53493                 mousemove = event;
53494             })
53495             .on('mouseover.vertices', function() {
53496                 if (map$$1.editable() && !transformed) {
53497                     var hover = event.target.__data__;
53498                     surface.selectAll('.data-layer-osm')
53499                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
53500                     dispatch$$1.call('drawn', this, {full: false});
53501                 }
53502             })
53503             .on('mouseout.vertices', function() {
53504                 if (map$$1.editable() && !transformed) {
53505                     var hover = event.relatedTarget && event.relatedTarget.__data__;
53506                     surface.selectAll('.data-layer-osm')
53507                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
53508                     dispatch$$1.call('drawn', this, {full: false});
53509                 }
53510             });
53511
53512         supersurface
53513             .call(context.background());
53514
53515         context.on('enter.map', function() {
53516             if (map$$1.editable() && !transformed) {
53517                 var all = context.intersects(map$$1.extent()),
53518                     filter = utilFunctor(true),
53519                     graph = context.graph();
53520
53521                 all = context.features().filter(all, graph);
53522                 surface.selectAll('.data-layer-osm')
53523                     .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
53524                     .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
53525                 dispatch$$1.call('drawn', this, {full: false});
53526             }
53527         });
53528
53529         map$$1.dimensions(utilGetDimensions(selection$$1));
53530
53531     }
53532
53533
53534     function ztok(z) {
53535         return 256 * Math.pow(2, z);
53536     }
53537
53538     function ktoz(k) {
53539         return Math.max(Math.log(k) / Math.LN2 - 8, 0);
53540     }
53541
53542     function pxCenter() {
53543         return [dimensions[0] / 2, dimensions[1] / 2];
53544     }
53545
53546
53547     function drawVector(difference, extent$$1) {
53548         var graph = context.graph(),
53549             features = context.features(),
53550             all = context.intersects(map$$1.extent()),
53551             data, filter;
53552
53553         if (difference) {
53554             var complete = difference.complete(map$$1.extent());
53555             data = lodash.compact(lodash.values(complete));
53556             filter = function(d) { return d.id in complete; };
53557             features.clear(data);
53558
53559         } else {
53560             // force a full redraw if gatherStats detects that a feature
53561             // should be auto-hidden (e.g. points or buildings)..
53562             if (features.gatherStats(all, graph, dimensions)) {
53563                 extent$$1 = undefined;
53564             }
53565
53566             if (extent$$1) {
53567                 data = context.intersects(map$$1.extent().intersection(extent$$1));
53568                 var set$$1 = set(lodash.map(data, 'id'));
53569                 filter = function(d) { return set$$1.has(d.id); };
53570
53571             } else {
53572                 data = all;
53573                 filter = utilFunctor(true);
53574             }
53575         }
53576
53577         data = features.filter(data, graph);
53578
53579         surface.selectAll('.data-layer-osm')
53580             .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
53581             .call(drawLines, graph, data, filter)
53582             .call(drawAreas, graph, data, filter)
53583             .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
53584             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
53585             .call(drawPoints, graph, data, filter);
53586
53587         dispatch$$1.call('drawn', this, {full: true});
53588     }
53589
53590
53591     function editOff() {
53592         context.features().resetStats();
53593         surface.selectAll('.layer-osm *').remove();
53594         dispatch$$1.call('drawn', this, {full: true});
53595     }
53596
53597
53598     function dblClick() {
53599         if (!dblclickEnabled) {
53600             event.preventDefault();
53601             event.stopImmediatePropagation();
53602         }
53603     }
53604
53605
53606     function zoomPan(manualEvent) {
53607         var eventTransform = (manualEvent || event).transform;
53608
53609         if (transformStart.x === eventTransform.x &&
53610             transformStart.y === eventTransform.y &&
53611             transformStart.k === eventTransform.k) {
53612             return;  // no change
53613         }
53614
53615         if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
53616             surface.interrupt();
53617             uiFlash(context.container())
53618                 .select('.content')
53619                 .text(t('cannot_zoom'));
53620             setZoom(context.minEditableZoom(), true);
53621             queueRedraw();
53622             dispatch$$1.call('move', this, map$$1);
53623             return;
53624         }
53625
53626         projection.transform(eventTransform);
53627
53628         var scale = eventTransform.k / transformStart.k,
53629             tX = (eventTransform.x / scale - transformStart.x) * scale,
53630             tY = (eventTransform.y / scale - transformStart.y) * scale;
53631
53632         transformed = true;
53633         utilSetTransform(supersurface, tX, tY, scale);
53634         queueRedraw();
53635
53636         dispatch$$1.call('move', this, map$$1);
53637     }
53638
53639
53640     function resetTransform() {
53641         if (!transformed) return false;
53642
53643         surface.selectAll('.radial-menu').interrupt().remove();
53644         utilSetTransform(supersurface, 0, 0);
53645         transformed = false;
53646         return true;
53647     }
53648
53649
53650     function redraw(difference, extent$$1) {
53651         if (!surface || !redrawEnabled) return;
53652
53653         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
53654         // It would result in artifacts where differenced entities are redrawn with
53655         // one transform and unchanged entities with another.
53656         if (resetTransform()) {
53657             difference = extent$$1 = undefined;
53658         }
53659
53660         var z = String(~~map$$1.zoom());
53661         if (surface.attr('data-zoom') !== z) {
53662             surface.attr('data-zoom', z)
53663                 .classed('low-zoom', z <= 16);
53664         }
53665
53666         if (!difference) {
53667             supersurface.call(context.background());
53668         }
53669
53670         wrapper
53671             .call(drawLayers);
53672
53673         // OSM
53674         if (map$$1.editable()) {
53675             context.loadTiles(projection, dimensions);
53676             drawVector(difference, extent$$1);
53677         } else {
53678             editOff();
53679         }
53680
53681         transformStart = projection.transform();
53682
53683         return map$$1;
53684     }
53685
53686
53687     var queueRedraw = lodash.throttle(redraw, 750);
53688
53689
53690     var immediateRedraw = function(difference, extent$$1) {
53691         if (!difference && !extent$$1) queueRedraw.cancel();
53692         redraw(difference, extent$$1);
53693     };
53694
53695
53696     function pointLocation(p) {
53697         var translate = projection.translate(),
53698             scale = projection.scale() * 2 * Math.PI;
53699         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
53700     }
53701
53702
53703     function locationPoint(l) {
53704         var translate = projection.translate(),
53705             scale = projection.scale() * 2 * Math.PI;
53706         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
53707     }
53708
53709
53710     map$$1.mouse = function() {
53711         var e = mousemove || event, s;
53712         while ((s = e.sourceEvent)) e = s;
53713         return mouse$$1(e);
53714     };
53715
53716
53717     map$$1.mouseCoordinates = function() {
53718         return projection.invert(map$$1.mouse());
53719     };
53720
53721
53722     map$$1.dblclickEnable = function(_) {
53723         if (!arguments.length) return dblclickEnabled;
53724         dblclickEnabled = _;
53725         return map$$1;
53726     };
53727
53728
53729     map$$1.redrawEnable = function(_) {
53730         if (!arguments.length) return redrawEnabled;
53731         redrawEnabled = _;
53732         return map$$1;
53733     };
53734
53735
53736     function setZoom(z2, force, duration) {
53737         if (z2 === map$$1.zoom() && !force) {
53738             return false;
53739         }
53740
53741         var k = projection.scale(),
53742             k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
53743             center = pxCenter(),
53744             l = pointLocation(center);
53745
53746         projection.scale(k2);
53747
53748         var t$$1 = projection.translate();
53749         l = locationPoint(l);
53750
53751         t$$1[0] += center[0] - l[0];
53752         t$$1[1] += center[1] - l[1];
53753
53754         if (duration) {
53755             projection.scale(k);  // reset scale
53756             _selection
53757                 .transition()
53758                 .duration(duration)
53759                 .on('start', function() { map$$1.startEase(); })
53760                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k2));
53761         } else {
53762             projection.translate(t$$1);
53763             transformStart = projection.transform();
53764             _selection.call(zoom$$1.transform, transformStart);
53765         }
53766
53767         return true;
53768     }
53769
53770
53771     function setCenter(loc2, duration) {
53772         var c = map$$1.center();
53773         if (loc2[0] === c[0] && loc2[1] === c[1]) {
53774             return false;
53775         }
53776
53777         var t$$1 = projection.translate(),
53778             k = projection.scale(),
53779             pxC = pxCenter(),
53780             ll = projection(loc2);
53781
53782         t$$1[0] = t$$1[0] - ll[0] + pxC[0];
53783         t$$1[1] = t$$1[1] - ll[1] + pxC[1];
53784
53785         if (duration) {
53786             _selection
53787                 .transition()
53788                 .duration(duration)
53789                 .on('start', function() { map$$1.startEase(); })
53790                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k));
53791         } else {
53792             projection.translate(t$$1);
53793             transformStart = projection.transform();
53794             _selection.call(zoom$$1.transform, transformStart);
53795         }
53796
53797         return true;
53798     }
53799
53800
53801     map$$1.pan = function(delta, duration) {
53802         var t$$1 = projection.translate(),
53803             k = projection.scale();
53804
53805         t$$1[0] += delta[0];
53806         t$$1[1] += delta[1];
53807
53808         if (duration) {
53809             _selection
53810                 .transition()
53811                 .duration(duration)
53812                 .on('start', function() { map$$1.startEase(); })
53813                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k));
53814         } else {
53815             projection.translate(t$$1);
53816             transformStart = projection.transform();
53817             _selection.call(zoom$$1.transform, transformStart);
53818             dispatch$$1.call('move', this, map$$1);
53819             immediateRedraw();
53820         }
53821
53822         return map$$1;
53823     };
53824
53825
53826     map$$1.dimensions = function(_) {
53827         if (!arguments.length) return dimensions;
53828         var center = map$$1.center();
53829         dimensions = _;
53830         drawLayers.dimensions(dimensions);
53831         context.background().dimensions(dimensions);
53832         projection.clipExtent([[0, 0], dimensions]);
53833         mouse$$1 = utilFastMouse(supersurface.node());
53834         setCenter(center);
53835
53836         queueRedraw();
53837         return map$$1;
53838     };
53839
53840
53841     function zoomIn(delta) {
53842         setZoom(~~map$$1.zoom() + delta, true, 250);
53843     }
53844
53845     function zoomOut(delta) {
53846         setZoom(~~map$$1.zoom() - delta, true, 250);
53847     }
53848
53849     map$$1.zoomIn = function() { zoomIn(1); };
53850     map$$1.zoomInFurther = function() { zoomIn(4); };
53851
53852     map$$1.zoomOut = function() { zoomOut(1); };
53853     map$$1.zoomOutFurther = function() { zoomOut(4); };
53854
53855
53856     map$$1.center = function(loc2) {
53857         if (!arguments.length) {
53858             return projection.invert(pxCenter());
53859         }
53860
53861         if (setCenter(loc2)) {
53862             dispatch$$1.call('move', this, map$$1);
53863         }
53864
53865         queueRedraw();
53866         return map$$1;
53867     };
53868
53869
53870     map$$1.zoom = function(z2) {
53871         if (!arguments.length) {
53872             return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
53873         }
53874
53875         if (z2 < minzoom) {
53876             surface.interrupt();
53877             uiFlash(context.container())
53878                 .select('.content')
53879                 .text(t('cannot_zoom'));
53880             z2 = context.minEditableZoom();
53881         }
53882
53883         if (setZoom(z2)) {
53884             dispatch$$1.call('move', this, map$$1);
53885         }
53886
53887         queueRedraw();
53888         return map$$1;
53889     };
53890
53891
53892     map$$1.zoomTo = function(entity, zoomLimits) {
53893         var extent$$1 = entity.extent(context.graph());
53894         if (!isFinite(extent$$1.area())) return;
53895
53896         var z2 = map$$1.trimmedExtentZoom(extent$$1);
53897         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
53898         map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
53899     };
53900
53901
53902     map$$1.centerZoom = function(loc2, z2) {
53903         var centered = setCenter(loc2),
53904             zoomed   = setZoom(z2);
53905
53906         if (centered || zoomed) {
53907             dispatch$$1.call('move', this, map$$1);
53908         }
53909
53910         queueRedraw();
53911         return map$$1;
53912     };
53913
53914
53915     map$$1.centerEase = function(loc2, duration) {
53916         duration = duration || 250;
53917         setCenter(loc2, duration);
53918         return map$$1;
53919     };
53920
53921
53922     map$$1.zoomEase = function(z2, duration) {
53923         duration = duration || 250;
53924         setZoom(z2, false, duration);
53925         return map$$1;
53926     };
53927
53928
53929     map$$1.startEase = function() {
53930         utilBindOnce(surface, 'mousedown.ease', function() {
53931             map$$1.cancelEase();
53932         });
53933         return map$$1;
53934     };
53935
53936
53937     map$$1.cancelEase = function() {
53938         _selection.interrupt();
53939         return map$$1;
53940     };
53941
53942
53943     map$$1.extent = function(_) {
53944         if (!arguments.length) {
53945             return new geoExtent$$1(projection.invert([0, dimensions[1]]),
53946                                  projection.invert([dimensions[0], 0]));
53947         } else {
53948             var extent$$1 = geoExtent$$1(_);
53949             map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
53950         }
53951     };
53952
53953
53954     map$$1.trimmedExtent = function(_) {
53955         if (!arguments.length) {
53956             var headerY = 60, footerY = 30, pad = 10;
53957             return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
53958                                  projection.invert([dimensions[0] - pad, headerY + pad]));
53959         } else {
53960             var extent$$1 = geoExtent$$1(_);
53961             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
53962         }
53963     };
53964
53965
53966     function calcZoom(extent$$1, dim) {
53967         var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
53968             br = projection([extent$$1[1][0], extent$$1[0][1]]);
53969
53970         // Calculate maximum zoom that fits extent
53971         var hFactor = (br[0] - tl[0]) / dim[0],
53972             vFactor = (br[1] - tl[1]) / dim[1],
53973             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
53974             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
53975             newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
53976
53977         return newZoom;
53978     }
53979
53980
53981     map$$1.extentZoom = function(_) {
53982         return calcZoom(geoExtent$$1(_), dimensions);
53983     };
53984
53985
53986     map$$1.trimmedExtentZoom = function(_) {
53987         var trimY = 120, trimX = 40,
53988             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
53989         return calcZoom(geoExtent$$1(_), trimmed);
53990     };
53991
53992
53993     map$$1.editable = function() {
53994         return map$$1.zoom() >= context.minEditableZoom();
53995     };
53996
53997
53998     map$$1.minzoom = function(_) {
53999         if (!arguments.length) return minzoom;
54000         minzoom = _;
54001         return map$$1;
54002     };
54003
54004
54005     map$$1.layers = drawLayers;
54006
54007
54008     return utilRebind(map$$1, dispatch$$1, 'on');
54009 }
54010
54011 var TAU = 2 * Math.PI;
54012 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
54013 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
54014 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
54015 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
54016
54017
54018 function uiMapInMap(context) {
54019     var key = '/';
54020
54021
54022     function map_in_map(selection$$1) {
54023         var backgroundLayer = rendererTileLayer(context),
54024             overlayLayers = {},
54025             projection = geoRawMercator(),
54026             gpxLayer = svgGpx(projection, context).showLabels(false),
54027             debugLayer = svgDebug(projection, context),
54028             zoom$$1 = zoom()
54029                 .scaleExtent([ztok(0.5), ztok(24)])
54030                 .on('start', zoomStarted)
54031                 .on('zoom', zoomed)
54032                 .on('end', zoomEnded),
54033             isTransformed = false,
54034             isHidden = true,
54035             skipEvents = false,
54036             gesture = null,
54037             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
54038             wrap = select(null),
54039             tiles = select(null),
54040             viewport = select(null),
54041             tStart,  // transform at start of gesture
54042             tCurr,   // transform at most recent event
54043             timeoutId;
54044
54045
54046         function zoomStarted() {
54047             if (skipEvents) return;
54048             tStart = tCurr = projection.transform();
54049             gesture = null;
54050         }
54051
54052
54053         function zoomed() {
54054             if (skipEvents) return;
54055
54056             var x = event.transform.x,
54057                 y = event.transform.y,
54058                 k = event.transform.k,
54059                 isZooming = (k !== tStart.k),
54060                 isPanning = (x !== tStart.x || y !== tStart.y);
54061
54062             if (!isZooming && !isPanning) {
54063                 return;  // no change
54064             }
54065
54066             // lock in either zooming or panning, don't allow both in minimap.
54067             if (!gesture) {
54068                 gesture = isZooming ? 'zoom' : 'pan';
54069             }
54070
54071             var tMini = projection.transform(),
54072                 tX, tY, scale;
54073
54074             if (gesture === 'zoom') {
54075                 var dMini = utilGetDimensions(wrap),
54076                     cMini = vecScale(dMini, 0.5);
54077                 scale = k / tMini.k;
54078                 tX = (cMini[0] / scale - cMini[0]) * scale;
54079                 tY = (cMini[1] / scale - cMini[1]) * scale;
54080             } else {
54081                 k = tMini.k;
54082                 scale = 1;
54083                 tX = x - tMini.x;
54084                 tY = y - tMini.y;
54085             }
54086
54087             utilSetTransform(tiles, tX, tY, scale);
54088             utilSetTransform(viewport, 0, 0, scale);
54089             isTransformed = true;
54090             tCurr = identity$6.translate(x, y).scale(k);
54091
54092             var zMain = ktoz(context.projection.scale()),
54093                 zMini = ktoz(k);
54094
54095             zDiff = zMain - zMini;
54096
54097             queueRedraw();
54098         }
54099
54100
54101         function zoomEnded() {
54102             if (skipEvents) return;
54103             if (gesture !== 'pan') return;
54104
54105             updateProjection();
54106             gesture = null;
54107             var dMini = utilGetDimensions(wrap),
54108                 cMini = vecScale(dMini, 0.5);
54109             context.map().center(projection.invert(cMini));   // recenter main map..
54110         }
54111
54112
54113         function updateProjection() {
54114             var loc = context.map().center(),
54115                 dMini = utilGetDimensions(wrap),
54116                 cMini = vecScale(dMini, 0.5),
54117                 tMain = context.projection.transform(),
54118                 zMain = ktoz(tMain.k),
54119                 zMini = Math.max(zMain - zDiff, 0.5),
54120                 kMini = ztok(zMini);
54121
54122             projection
54123                 .translate([tMain.x, tMain.y])
54124                 .scale(kMini);
54125
54126             var point = projection(loc),
54127                 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
54128                 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
54129                 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
54130
54131             projection
54132                 .translate([xMini, yMini])
54133                 .clipExtent([[0, 0], dMini]);
54134
54135             tCurr = projection.transform();
54136
54137             if (isTransformed) {
54138                 utilSetTransform(tiles, 0, 0);
54139                 utilSetTransform(viewport, 0, 0);
54140                 isTransformed = false;
54141             }
54142
54143             zoom$$1
54144                 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
54145
54146             skipEvents = true;
54147             wrap.call(zoom$$1.transform, tCurr);
54148             skipEvents = false;
54149         }
54150
54151
54152         function redraw() {
54153             clearTimeout(timeoutId);
54154             if (isHidden) return;
54155
54156             updateProjection();
54157
54158             var dMini = utilGetDimensions(wrap),
54159                 zMini = ktoz(projection.scale());
54160
54161             // setup tile container
54162             tiles = wrap
54163                 .selectAll('.map-in-map-tiles')
54164                 .data([0]);
54165
54166             tiles = tiles.enter()
54167                 .append('div')
54168                 .attr('class', 'map-in-map-tiles')
54169                 .merge(tiles);
54170
54171             // redraw background
54172             backgroundLayer
54173                 .source(context.background().baseLayerSource())
54174                 .projection(projection)
54175                 .dimensions(dMini);
54176
54177             var background = tiles
54178                 .selectAll('.map-in-map-background')
54179                 .data([0]);
54180
54181             background.enter()
54182                 .append('div')
54183                 .attr('class', 'map-in-map-background')
54184                 .merge(background)
54185                 .call(backgroundLayer);
54186
54187
54188             // redraw overlay
54189             var overlaySources = context.background().overlayLayerSources();
54190             var activeOverlayLayers = [];
54191             for (var i = 0; i < overlaySources.length; i++) {
54192                 if (overlaySources[i].validZoom(zMini)) {
54193                     if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
54194                     activeOverlayLayers.push(overlayLayers[i]
54195                         .source(overlaySources[i])
54196                         .projection(projection)
54197                         .dimensions(dMini));
54198                 }
54199             }
54200
54201             var overlay = tiles
54202                 .selectAll('.map-in-map-overlay')
54203                 .data([0]);
54204
54205             overlay = overlay.enter()
54206                 .append('div')
54207                 .attr('class', 'map-in-map-overlay')
54208                 .merge(overlay);
54209
54210
54211             var overlays = overlay
54212                 .selectAll('div')
54213                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
54214
54215             overlays.exit()
54216                 .remove();
54217
54218             overlays = overlays.enter()
54219                 .append('div')
54220                 .merge(overlays)
54221                 .each(function(layer) { select(this).call(layer); });
54222
54223
54224             var dataLayers = tiles
54225                 .selectAll('.map-in-map-data')
54226                 .data([0]);
54227
54228             dataLayers.exit()
54229                 .remove();
54230
54231             dataLayers = dataLayers.enter()
54232                 .append('svg')
54233                 .attr('class', 'map-in-map-data')
54234                 .merge(dataLayers)
54235                 .call(gpxLayer)
54236                 .call(debugLayer);
54237
54238
54239             // redraw viewport bounding box
54240             if (gesture !== 'pan') {
54241                 var getPath = index$5(projection),
54242                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
54243
54244                 viewport = wrap.selectAll('.map-in-map-viewport')
54245                     .data([0]);
54246
54247                 viewport = viewport.enter()
54248                     .append('svg')
54249                     .attr('class', 'map-in-map-viewport')
54250                     .merge(viewport);
54251
54252
54253                 var path$$1 = viewport.selectAll('.map-in-map-bbox')
54254                     .data([bbox]);
54255
54256                 path$$1.enter()
54257                     .append('path')
54258                     .attr('class', 'map-in-map-bbox')
54259                     .merge(path$$1)
54260                     .attr('d', getPath)
54261                     .classed('thick', function(d) { return getPath.area(d) < 30; });
54262             }
54263         }
54264
54265
54266         function queueRedraw() {
54267             clearTimeout(timeoutId);
54268             timeoutId = setTimeout(function() { redraw(); }, 750);
54269         }
54270
54271
54272         function toggle() {
54273             if (event) event.preventDefault();
54274
54275             isHidden = !isHidden;
54276
54277             var label = select('.minimap-toggle');
54278             label.classed('active', !isHidden)
54279                 .select('input').property('checked', !isHidden);
54280
54281             if (isHidden) {
54282                 wrap
54283                     .style('display', 'block')
54284                     .style('opacity', '1')
54285                     .transition()
54286                     .duration(200)
54287                     .style('opacity', '0')
54288                     .on('end', function() {
54289                         selection$$1.selectAll('.map-in-map')
54290                             .style('display', 'none');
54291                     });
54292             } else {
54293                 wrap
54294                     .style('display', 'block')
54295                     .style('opacity', '0')
54296                     .transition()
54297                     .duration(200)
54298                     .style('opacity', '1')
54299                     .on('end', function() {
54300                         redraw();
54301                     });
54302             }
54303         }
54304
54305
54306         uiMapInMap.toggle = toggle;
54307
54308         wrap = selection$$1.selectAll('.map-in-map')
54309             .data([0]);
54310
54311         wrap = wrap.enter()
54312             .append('div')
54313             .attr('class', 'map-in-map')
54314             .style('display', (isHidden ? 'none' : 'block'))
54315             .call(zoom$$1)
54316             .on('dblclick.zoom', null)
54317             .merge(wrap);
54318
54319         context.map()
54320             .on('drawn.map-in-map', function(drawn) {
54321                 if (drawn.full === true) {
54322                     redraw();
54323                 }
54324             });
54325
54326         redraw();
54327
54328         var keybinding = d3keybinding('map-in-map')
54329             .on(key, toggle);
54330
54331         select(document)
54332             .call(keybinding);
54333     }
54334
54335     return map_in_map;
54336 }
54337
54338 function uiTooltipHtml(text, key) {
54339     var s = '<span>' + text + '</span>';
54340     if (key) {
54341         s += '<div class="keyhint-wrap">' +
54342             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
54343             '<span class="keyhint"> ' + key + '</span></div>';
54344     }
54345     return s;
54346 }
54347
54348 function uiBackground(context) {
54349     var key = 'B',
54350         detected = utilDetect(),
54351         opacities = [1, 0.75, 0.5, 0.25],
54352         directions = [
54353             ['right', [0.5, 0]],
54354             ['top', [0, -0.5]],
54355             ['left', [-0.5, 0]],
54356             ['bottom', [0, 0.5]]],
54357         opacityDefault = (context.storage('background-opacity') !== null) ?
54358             (+context.storage('background-opacity')) : 1.0,
54359         customTemplate = context.storage('background-custom-template') || '',
54360         previous;
54361
54362     // Can be 0 from <1.3.0 use or due to issue #1923.
54363     if (opacityDefault === 0) opacityDefault = 1.0;
54364
54365
54366     function background(selection$$1) {
54367
54368         function sortSources(a, b) {
54369             return a.best() && !b.best() ? -1
54370                 : b.best() && !a.best() ? 1
54371                 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
54372         }
54373
54374
54375         function setOpacity(d) {
54376             var bg = context.container().selectAll('.layer-background')
54377                 .transition()
54378                 .style('opacity', d)
54379                 .attr('data-opacity', d);
54380
54381             if (!detected.opera) {
54382                 utilSetTransform(bg, 0, 0);
54383             }
54384
54385             opacityList.selectAll('li')
54386                 .classed('active', function(_) { return _ === d; });
54387
54388             context.storage('background-opacity', d);
54389         }
54390
54391
54392         function setTooltips(selection$$1) {
54393             selection$$1.each(function(d, i, nodes) {
54394                 var item = select(this).select('label'),
54395                     placement = (i < nodes.length / 2) ? 'bottom' : 'top';
54396
54397                 if (d === previous) {
54398                     item.call(tooltip()
54399                         .placement(placement)
54400                         .html(true)
54401                         .title(function() {
54402                             var tip = '<div>' + t('background.switch') + '</div>';
54403                             return uiTooltipHtml(tip, uiCmd('⌘B'));
54404                         })
54405                     );
54406                 } else if (d.description) {
54407                     item.call(tooltip()
54408                         .placement(placement)
54409                         .title(d.description)
54410                     );
54411                 } else {
54412                     item.call(tooltip().destroy);
54413                 }
54414             });
54415         }
54416
54417
54418         function selectLayer() {
54419             function active$$1(d) {
54420                 return context.background().showsLayer(d);
54421             }
54422
54423             content.selectAll('.layer, .custom_layer')
54424                 .classed('active', active$$1)
54425                 .classed('switch', function(d) { return d === previous; })
54426                 .call(setTooltips)
54427                 .selectAll('input')
54428                 .property('checked', active$$1);
54429         }
54430
54431
54432         function clickSetSource(d) {
54433             event.preventDefault();
54434             previous = context.background().baseLayerSource();
54435             context.background().baseLayerSource(d);
54436             selectLayer();
54437             document.activeElement.blur();
54438         }
54439
54440
54441         function editCustom() {
54442             event.preventDefault();
54443             var template = window.prompt(t('background.custom_prompt'), customTemplate);
54444             if (!template ||
54445                 template.indexOf('google.com') !== -1 ||
54446                 template.indexOf('googleapis.com') !== -1 ||
54447                 template.indexOf('google.ru') !== -1) {
54448                 selectLayer();
54449                 return;
54450             }
54451             setCustom(template);
54452         }
54453
54454
54455         function setCustom(template) {
54456             context.storage('background-custom-template', template);
54457             var d = rendererBackgroundSource.Custom(template);
54458             content.selectAll('.custom_layer').datum(d);
54459             clickSetSource(d);
54460         }
54461
54462
54463         function clickSetOverlay(d) {
54464             event.preventDefault();
54465             context.background().toggleOverlayLayer(d);
54466             selectLayer();
54467             document.activeElement.blur();
54468         }
54469
54470
54471         function drawList(layerList, type, change, filter) {
54472             var sources = context.background()
54473                 .sources(context.map().extent())
54474                 .filter(filter);
54475
54476             var layerLinks = layerList.selectAll('li.layer')
54477                 .data(sources, function(d) { return d.name(); });
54478
54479             layerLinks.exit()
54480                 .remove();
54481
54482             var enter = layerLinks.enter()
54483                 .insert('li', '.custom_layer')
54484                 .attr('class', 'layer')
54485                 .classed('best', function(d) { return d.best(); });
54486
54487             enter.filter(function(d) { return d.best(); })
54488                 .append('div')
54489                 .attr('class', 'best')
54490                 .call(tooltip()
54491                     .title(t('background.best_imagery'))
54492                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
54493                 .append('span')
54494                 .html('&#9733;');
54495
54496             var label = enter
54497                 .append('label');
54498
54499             label
54500                 .append('input')
54501                 .attr('type', type)
54502                 .attr('name', 'layers')
54503                 .on('change', change);
54504
54505             label
54506                 .append('span')
54507                 .text(function(d) { return d.name(); });
54508
54509
54510             layerList.selectAll('li.layer')
54511                 .sort(sortSources)
54512                 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
54513         }
54514
54515
54516         function update() {
54517             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
54518             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
54519
54520             selectLayer();
54521
54522             var source = context.background().baseLayerSource();
54523             if (source.id === 'custom') {
54524                 customTemplate = source.template;
54525             }
54526
54527             updateOffsetVal();
54528         }
54529
54530
54531         function updateOffsetVal() {
54532             var meters = geoOffsetToMeters(context.background().offset()),
54533                 x = +meters[0].toFixed(2),
54534                 y = +meters[1].toFixed(2);
54535
54536             selectAll('.nudge-inner-rect')
54537                 .select('input')
54538                 .classed('error', false)
54539                 .property('value', x + ', ' + y);
54540
54541             selectAll('.nudge-reset')
54542                 .classed('disabled', function() {
54543                     return (x === 0 && y === 0);
54544                 });
54545         }
54546
54547
54548         function resetOffset() {
54549             if (event.button !== 0) return;
54550             context.background().offset([0, 0]);
54551             updateOffsetVal();
54552         }
54553
54554
54555         function nudge(d) {
54556             context.background().nudge(d, context.map().zoom());
54557             updateOffsetVal();
54558         }
54559
54560
54561         function buttonOffset(d) {
54562             if (event.button !== 0) return;
54563             var timeout$$1 = window.setTimeout(function() {
54564                     interval$$1 = window.setInterval(nudge.bind(null, d), 100);
54565                 }, 500),
54566                 interval$$1;
54567
54568             function doneNudge() {
54569                 window.clearTimeout(timeout$$1);
54570                 window.clearInterval(interval$$1);
54571                 select(window)
54572                     .on('mouseup.buttonoffset', null, true)
54573                     .on('mousedown.buttonoffset', null, true);
54574             }
54575
54576             select(window)
54577                 .on('mouseup.buttonoffset', doneNudge, true)
54578                 .on('mousedown.buttonoffset', doneNudge, true);
54579
54580             nudge(d);
54581         }
54582
54583
54584         function inputOffset() {
54585             if (event.button !== 0) return;
54586             var input = select(this);
54587             var d = input.node().value;
54588
54589             if (d === '') return resetOffset();
54590
54591             d = d.replace(/;/g, ',').split(',').map(function(n) {
54592                 // if n is NaN, it will always get mapped to false.
54593                 return !isNaN(n) && n;
54594             });
54595
54596             if (d.length !== 2 || !d[0] || !d[1]) {
54597                 input.classed('error', true);
54598                 return;
54599             }
54600
54601             context.background().offset(geoMetersToOffset(d));
54602             updateOffsetVal();
54603         }
54604
54605
54606         function dragOffset() {
54607             if (event.button !== 0) return;
54608             var origin = [event.clientX, event.clientY];
54609
54610             context.container()
54611                 .append('div')
54612                 .attr('class', 'nudge-surface');
54613
54614             select(window)
54615                 .on('mousemove.offset', function() {
54616                     var latest = [event.clientX, event.clientY];
54617                     var d = [
54618                         -(origin[0] - latest[0]) / 4,
54619                         -(origin[1] - latest[1]) / 4
54620                     ];
54621
54622                     origin = latest;
54623                     nudge(d);
54624                 })
54625                 .on('mouseup.offset', function() {
54626                     if (event.button !== 0) return;
54627                     selectAll('.nudge-surface')
54628                         .remove();
54629
54630                     select(window)
54631                         .on('mousemove.offset', null)
54632                         .on('mouseup.offset', null);
54633                 });
54634
54635             event.preventDefault();
54636         }
54637
54638
54639         function hide() {
54640             setVisible(false);
54641         }
54642
54643
54644         function toggle() {
54645             if (event) event.preventDefault();
54646             tooltipBehavior.hide(button);
54647             setVisible(!button.classed('active'));
54648         }
54649
54650
54651         function quickSwitch() {
54652             if (previous) {
54653                 clickSetSource(previous);
54654             }
54655         }
54656
54657
54658         function setVisible(show) {
54659             if (show !== shown) {
54660                 button.classed('active', show);
54661                 shown = show;
54662
54663                 if (show) {
54664                     selection$$1.on('mousedown.background-inside', function() {
54665                         event.stopPropagation();
54666                     });
54667                     content
54668                         .style('display', 'block')
54669                         .style('right', '-300px')
54670                         .transition()
54671                         .duration(200)
54672                         .style('right', '0px');
54673                 } else {
54674                     content
54675                         .style('display', 'block')
54676                         .style('right', '0px')
54677                         .transition()
54678                         .duration(200)
54679                         .style('right', '-300px')
54680                         .on('end', function() {
54681                             select(this).style('display', 'none');
54682                         });
54683                     selection$$1.on('mousedown.background-inside', null);
54684                 }
54685             }
54686         }
54687
54688
54689         var content = selection$$1
54690                 .append('div')
54691                 .attr('class', 'fillL map-overlay col3 content hide'),
54692             tooltipBehavior = tooltip()
54693                 .placement((textDirection === 'rtl') ? 'right' : 'left')
54694                 .html(true)
54695                 .title(uiTooltipHtml(t('background.description'), key)),
54696             button = selection$$1
54697                 .append('button')
54698                 .attr('tabindex', -1)
54699                 .on('click', toggle)
54700                 .call(svgIcon('#icon-layers', 'light'))
54701                 .call(tooltipBehavior),
54702             shown = false;
54703
54704
54705         /* opacity switcher */
54706
54707         var opawrap = content
54708                 .append('div')
54709                 .attr('class', 'opacity-options-wrapper');
54710
54711         opawrap
54712             .append('h4')
54713             .text(t('background.title'));
54714
54715         var opacityList = opawrap
54716             .append('ul')
54717             .attr('class', 'opacity-options');
54718
54719         opacityList.selectAll('div.opacity')
54720             .data(opacities)
54721             .enter()
54722             .append('li')
54723             .attr('data-original-title', function(d) {
54724                 return t('background.percent_brightness', { opacity: (d * 100) });
54725             })
54726             .on('click.set-opacity', setOpacity)
54727             .html('<div class="select-box"></div>')
54728             .call(tooltip()
54729                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
54730             .append('div')
54731             .attr('class', 'opacity')
54732             .style('opacity', function(d) { return 1.25 - d; });
54733
54734
54735         /* background switcher */
54736
54737         var backgroundList = content
54738             .append('ul')
54739             .attr('class', 'layer-list')
54740             .attr('dir', 'auto');
54741
54742         var custom = backgroundList
54743             .append('li')
54744             .attr('class', 'custom_layer')
54745             .datum(rendererBackgroundSource.Custom());
54746
54747         custom
54748             .append('button')
54749             .attr('class', 'layer-browse')
54750             .call(tooltip()
54751                 .title(t('background.custom_button'))
54752                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
54753             .on('click', editCustom)
54754             .call(svgIcon('#icon-search'));
54755
54756         var label = custom
54757             .append('label');
54758
54759         label
54760             .append('input')
54761             .attr('type', 'radio')
54762             .attr('name', 'layers')
54763             .on('change', function () {
54764                 if (customTemplate) {
54765                     setCustom(customTemplate);
54766                 } else {
54767                     editCustom();
54768                 }
54769             });
54770
54771         label
54772             .append('span')
54773             .text(t('background.custom'));
54774
54775         content
54776             .append('div')
54777             .attr('class', 'imagery-faq')
54778             .append('a')
54779             .attr('target', '_blank')
54780             .attr('tabindex', -1)
54781             .call(svgIcon('#icon-out-link', 'inline'))
54782             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
54783             .append('span')
54784             .text(t('background.imagery_source_faq'));
54785
54786         var overlayList = content
54787             .append('ul')
54788             .attr('class', 'layer-list');
54789
54790         var controls = content
54791             .append('div')
54792             .attr('class', 'controls-list');
54793
54794
54795         /* minimap toggle */
54796
54797         var minimapLabel = controls
54798             .append('label')
54799             .call(tooltip()
54800                 .html(true)
54801                 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
54802                 .placement('top')
54803             );
54804
54805         minimapLabel
54806             .classed('minimap-toggle', true)
54807             .append('input')
54808             .attr('type', 'checkbox')
54809             .on('change', function() {
54810                 uiMapInMap.toggle();
54811                 event.preventDefault();
54812             });
54813
54814         minimapLabel
54815             .append('span')
54816             .text(t('background.minimap.description'));
54817
54818
54819         /* imagery offset controls */
54820
54821         var adjustments = content
54822             .append('div')
54823             .attr('class', 'adjustments');
54824
54825         adjustments
54826             .append('a')
54827             .text(t('background.fix_misalignment'))
54828             .attr('href', '#')
54829             .classed('hide-toggle', true)
54830             .classed('expanded', false)
54831             .on('click', function() {
54832                 if (event.button !== 0) return;
54833                 var exp = select(this).classed('expanded');
54834                 nudgeContainer.style('display', exp ? 'none' : 'block');
54835                 select(this).classed('expanded', !exp);
54836                 event.preventDefault();
54837             });
54838
54839         var nudgeContainer = adjustments
54840             .append('div')
54841             .attr('class', 'nudge-container cf')
54842             .style('display', 'none');
54843
54844         nudgeContainer
54845             .append('div')
54846             .attr('class', 'nudge-instructions')
54847             .text(t('background.offset'));
54848
54849         var nudgeRect = nudgeContainer
54850             .append('div')
54851             .attr('class', 'nudge-outer-rect')
54852             .on('mousedown', dragOffset);
54853
54854         nudgeRect
54855             .append('div')
54856             .attr('class', 'nudge-inner-rect')
54857             .append('input')
54858             .on('change', inputOffset)
54859             .on('mousedown', function() {
54860                 if (event.button !== 0) return;
54861                 event.stopPropagation();
54862             });
54863
54864         nudgeContainer
54865             .append('div')
54866             .selectAll('button')
54867             .data(directions).enter()
54868             .append('button')
54869             .attr('class', function(d) { return d[0] + ' nudge'; })
54870             .on('mousedown', function(d) {
54871                 if (event.button !== 0) return;
54872                 buttonOffset(d[1]);
54873             });
54874
54875         nudgeContainer
54876             .append('button')
54877             .attr('title', t('background.reset'))
54878             .attr('class', 'nudge-reset disabled')
54879             .on('click', resetOffset)
54880             .call(
54881                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
54882             );
54883
54884         context.map()
54885             .on('move.background-update', lodash.debounce(update, 1000));
54886
54887         context.background()
54888             .on('change.background-update', update);
54889
54890
54891         update();
54892         setOpacity(opacityDefault);
54893
54894         var keybinding = d3keybinding('background')
54895             .on(key, toggle)
54896             .on(uiCmd('⌘B'), quickSwitch)
54897             .on('F', hide)
54898             .on('H', hide);
54899
54900         select(document)
54901             .call(keybinding);
54902
54903         context.surface().on('mousedown.background-outside', hide);
54904         context.container().on('mousedown.background-outside', hide);
54905     }
54906
54907     return background;
54908 }
54909
54910 function uiContributors(context) {
54911     var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
54912         limit = 4,
54913         hidden = false,
54914         wrap = select(null);
54915
54916
54917     function update() {
54918         var users = {},
54919             entities = context.intersects(context.map().extent());
54920
54921         entities.forEach(function(entity) {
54922             if (entity && entity.user) users[entity.user] = true;
54923         });
54924
54925         var u = Object.keys(users),
54926             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
54927
54928         wrap.html('')
54929             .call(svgIcon('#icon-nearby', 'pre-text light'));
54930
54931         var userList = select(document.createElement('span'));
54932
54933         userList.selectAll()
54934             .data(subset)
54935             .enter()
54936             .append('a')
54937             .attr('class', 'user-link')
54938             .attr('href', function(d) { return context.connection().userURL(d); })
54939             .attr('target', '_blank')
54940             .attr('tabindex', -1)
54941             .text(String);
54942
54943         if (u.length > limit) {
54944             var count = select(document.createElement('span'));
54945
54946             count.append('a')
54947                 .attr('target', '_blank')
54948                 .attr('tabindex', -1)
54949                 .attr('href', function() {
54950                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
54951                 })
54952                 .text(u.length - limit + 1);
54953
54954             wrap.append('span')
54955                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
54956
54957         } else {
54958             wrap.append('span')
54959                 .html(t('contributors.list', { users: userList.html() }));
54960         }
54961
54962         if (!u.length) {
54963             hidden = true;
54964             wrap
54965                 .transition()
54966                 .style('opacity', 0);
54967
54968         } else if (hidden) {
54969             wrap
54970                 .transition()
54971                 .style('opacity', 1);
54972         }
54973     }
54974
54975
54976     return function(selection$$1) {
54977         wrap = selection$$1;
54978         update();
54979
54980         context.connection().on('loaded.contributors', debouncedUpdate);
54981         context.map().on('move.contributors', debouncedUpdate);
54982     };
54983 }
54984
54985 function uiFeatureInfo(context) {
54986     function update(selection$$1) {
54987         var features = context.features(),
54988             stats = features.stats(),
54989             count = 0,
54990             hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
54991                 if (stats[k]) {
54992                     count += stats[k];
54993                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
54994                 }
54995             }));
54996
54997         selection$$1.html('');
54998
54999         if (hiddenList.length) {
55000             var tooltipBehavior = tooltip()
55001                     .placement('top')
55002                     .html(true)
55003                     .title(function() {
55004                         return uiTooltipHtml(hiddenList.join('<br/>'));
55005                     });
55006
55007             var warning = selection$$1.append('a')
55008                 .attr('href', '#')
55009                 .attr('tabindex', -1)
55010                 .html(t('feature_info.hidden_warning', { count: count }))
55011                 .call(tooltipBehavior)
55012                 .on('click', function() {
55013                     tooltipBehavior.hide(warning);
55014                     // open map data panel?
55015                     event.preventDefault();
55016                 });
55017         }
55018
55019         selection$$1
55020             .classed('hide', !hiddenList.length);
55021     }
55022
55023
55024     return function(selection$$1) {
55025         update(selection$$1);
55026
55027         context.features().on('change.feature_info', function() {
55028             update(selection$$1);
55029         });
55030     };
55031 }
55032
55033 function uiFullScreen(context) {
55034     var element = context.container().node(),
55035         keybinding = d3keybinding('full-screen');
55036         // button;
55037
55038
55039     function getFullScreenFn() {
55040         if (element.requestFullscreen) {
55041             return element.requestFullscreen;
55042         } else if (element.msRequestFullscreen) {
55043             return element.msRequestFullscreen;
55044         } else if (element.mozRequestFullScreen) {
55045             return element.mozRequestFullScreen;
55046         } else if (element.webkitRequestFullscreen) {
55047             return element.webkitRequestFullscreen;
55048         }
55049     }
55050
55051
55052     function getExitFullScreenFn() {
55053         if (document.exitFullscreen) {
55054             return document.exitFullscreen;
55055         } else if (document.msExitFullscreen) {
55056             return document.msExitFullscreen;
55057         } else if (document.mozCancelFullScreen) {
55058             return document.mozCancelFullScreen;
55059         } else if (document.webkitExitFullscreen) {
55060             return document.webkitExitFullscreen;
55061         }
55062     }
55063
55064
55065     function isFullScreen() {
55066         return document.fullscreenElement ||
55067             document.mozFullScreenElement ||
55068             document.webkitFullscreenElement ||
55069             document.msFullscreenElement;
55070     }
55071
55072
55073     function isSupported() {
55074         return !!getFullScreenFn();
55075     }
55076
55077
55078     function fullScreen() {
55079         event.preventDefault();
55080         if (!isFullScreen()) {
55081             // button.classed('active', true);
55082             getFullScreenFn().apply(element);
55083         } else {
55084             // button.classed('active', false);
55085             getExitFullScreenFn().apply(document);
55086         }
55087     }
55088
55089
55090     return function() { // selection) {
55091         if (!isSupported())
55092             return;
55093
55094         // button = selection.append('button')
55095         //     .attr('title', t('full_screen'))
55096         //     .attr('tabindex', -1)
55097         //     .on('click', fullScreen)
55098         //     .call(tooltip);
55099
55100         // button.append('span')
55101         //     .attr('class', 'icon full-screen');
55102
55103         keybinding
55104             .on('f11', fullScreen)
55105             .on(uiCmd('⌘⇧F'), fullScreen);
55106
55107         select(document)
55108             .call(keybinding);
55109     };
55110 }
55111
55112 function uiModal(selection$$1, blocking) {
55113     var keybinding = d3keybinding('modal');
55114     var previous = selection$$1.select('div.modal');
55115     var animate = previous.empty();
55116
55117     previous.transition()
55118         .duration(200)
55119         .style('opacity', 0)
55120         .remove();
55121
55122     var shaded = selection$$1
55123         .append('div')
55124         .attr('class', 'shaded')
55125         .style('opacity', 0);
55126
55127     shaded.close = function() {
55128         shaded
55129             .transition()
55130             .duration(200)
55131             .style('opacity',0)
55132             .remove();
55133
55134         modal
55135             .transition()
55136             .duration(200)
55137             .style('top','0px');
55138
55139         keybinding.off();
55140     };
55141
55142
55143     var modal = shaded
55144         .append('div')
55145         .attr('class', 'modal fillL col6');
55146
55147     if (!blocking) {
55148         shaded.on('click.remove-modal', function() {
55149             if (event.target === this) {
55150                 shaded.close();
55151             }
55152         });
55153
55154         modal.append('button')
55155             .attr('class', 'close')
55156             .on('click', shaded.close)
55157             .call(svgIcon('#icon-close'));
55158
55159         keybinding
55160             .on('⌫', shaded.close)
55161             .on('⎋', shaded.close);
55162
55163         select(document)
55164             .call(keybinding);
55165     }
55166
55167     modal
55168         .append('div')
55169         .attr('class', 'content');
55170
55171     if (animate) {
55172         shaded.transition().style('opacity', 1);
55173     } else {
55174         shaded.style('opacity', 1);
55175     }
55176
55177
55178     return shaded;
55179 }
55180
55181 function uiLoading(context) {
55182     var message = '',
55183         blocking = false,
55184         modalSelection;
55185
55186
55187     var loading = function(selection) {
55188         modalSelection = uiModal(selection, blocking);
55189
55190         var loadertext = modalSelection.select('.content')
55191             .classed('loading-modal', true)
55192             .append('div')
55193             .attr('class', 'modal-section fillL');
55194
55195         loadertext
55196             .append('img')
55197             .attr('class', 'loader')
55198             .attr('src', context.imagePath('loader-white.gif'));
55199
55200         loadertext
55201             .append('h3')
55202             .text(message);
55203
55204         modalSelection.select('button.close')
55205             .attr('class', 'hide');
55206
55207         return loading;
55208     };
55209
55210
55211     loading.message = function(_) {
55212         if (!arguments.length) return message;
55213         message = _;
55214         return loading;
55215     };
55216
55217
55218     loading.blocking = function(_) {
55219         if (!arguments.length) return blocking;
55220         blocking = _;
55221         return loading;
55222     };
55223
55224
55225     loading.close = function() {
55226         modalSelection.remove();
55227     };
55228
55229
55230     return loading;
55231 }
55232
55233 function uiGeolocate(context) {
55234     var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
55235         locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
55236         timeoutId;
55237
55238
55239     function click() {
55240         context.enter(modeBrowse$$1(context));
55241         context.container().call(locating);
55242         navigator.geolocation.getCurrentPosition(success, error, geoOptions);
55243
55244         // This timeout ensures that we still call finish() even if
55245         // the user declines to share their location in Firefox
55246         timeoutId = setTimeout(finish, 10000 /* 10sec */ );
55247     }
55248
55249
55250     function success(position) {
55251         var map = context.map(),
55252             extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
55253                 .padByMeters(position.coords.accuracy);
55254
55255         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
55256         finish();
55257     }
55258
55259
55260     function error() {
55261         finish();
55262     }
55263
55264
55265     function finish() {
55266         locating.close();  // unblock ui
55267         if (timeoutId) { clearTimeout(timeoutId); }
55268         timeoutId = undefined;
55269     }
55270
55271
55272     return function(selection) {
55273         if (!navigator.geolocation) return;
55274
55275         selection
55276             .append('button')
55277             .attr('tabindex', -1)
55278             .attr('title', t('geolocate.title'))
55279             .on('click', click)
55280             .call(svgIcon('#icon-geolocate', 'light'))
55281             .call(tooltip()
55282                 .placement((textDirection === 'rtl') ? 'right' : 'left'));
55283     };
55284 }
55285
55286 var marked = createCommonjsModule(function (module, exports) {
55287 /**
55288  * marked - a markdown parser
55289  * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
55290  * https://github.com/chjj/marked
55291  */
55292
55293 (function() {
55294
55295 /**
55296  * Block-Level Grammar
55297  */
55298
55299 var block = {
55300   newline: /^\n+/,
55301   code: /^( {4}[^\n]+\n*)+/,
55302   fences: noop,
55303   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
55304   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
55305   nptable: noop,
55306   lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
55307   blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
55308   list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
55309   html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
55310   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
55311   table: noop,
55312   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
55313   text: /^[^\n]+/
55314 };
55315
55316 block.bullet = /(?:[*+-]|\d+\.)/;
55317 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
55318 block.item = replace(block.item, 'gm')
55319   (/bull/g, block.bullet)
55320   ();
55321
55322 block.list = replace(block.list)
55323   (/bull/g, block.bullet)
55324   ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
55325   ('def', '\\n+(?=' + block.def.source + ')')
55326   ();
55327
55328 block.blockquote = replace(block.blockquote)
55329   ('def', block.def)
55330   ();
55331
55332 block._tag = '(?!(?:'
55333   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
55334   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
55335   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
55336
55337 block.html = replace(block.html)
55338   ('comment', /<!--[\s\S]*?-->/)
55339   ('closed', /<(tag)[\s\S]+?<\/\1>/)
55340   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
55341   (/tag/g, block._tag)
55342   ();
55343
55344 block.paragraph = replace(block.paragraph)
55345   ('hr', block.hr)
55346   ('heading', block.heading)
55347   ('lheading', block.lheading)
55348   ('blockquote', block.blockquote)
55349   ('tag', '<' + block._tag)
55350   ('def', block.def)
55351   ();
55352
55353 /**
55354  * Normal Block Grammar
55355  */
55356
55357 block.normal = merge({}, block);
55358
55359 /**
55360  * GFM Block Grammar
55361  */
55362
55363 block.gfm = merge({}, block.normal, {
55364   fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
55365   paragraph: /^/,
55366   heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
55367 });
55368
55369 block.gfm.paragraph = replace(block.paragraph)
55370   ('(?!', '(?!'
55371     + block.gfm.fences.source.replace('\\1', '\\2') + '|'
55372     + block.list.source.replace('\\1', '\\3') + '|')
55373   ();
55374
55375 /**
55376  * GFM + Tables Block Grammar
55377  */
55378
55379 block.tables = merge({}, block.gfm, {
55380   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
55381   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
55382 });
55383
55384 /**
55385  * Block Lexer
55386  */
55387
55388 function Lexer(options) {
55389   this.tokens = [];
55390   this.tokens.links = {};
55391   this.options = options || marked.defaults;
55392   this.rules = block.normal;
55393
55394   if (this.options.gfm) {
55395     if (this.options.tables) {
55396       this.rules = block.tables;
55397     } else {
55398       this.rules = block.gfm;
55399     }
55400   }
55401 }
55402
55403 /**
55404  * Expose Block Rules
55405  */
55406
55407 Lexer.rules = block;
55408
55409 /**
55410  * Static Lex Method
55411  */
55412
55413 Lexer.lex = function(src, options) {
55414   var lexer = new Lexer(options);
55415   return lexer.lex(src);
55416 };
55417
55418 /**
55419  * Preprocessing
55420  */
55421
55422 Lexer.prototype.lex = function(src) {
55423   src = src
55424     .replace(/\r\n|\r/g, '\n')
55425     .replace(/\t/g, '    ')
55426     .replace(/\u00a0/g, ' ')
55427     .replace(/\u2424/g, '\n');
55428
55429   return this.token(src, true);
55430 };
55431
55432 /**
55433  * Lexing
55434  */
55435
55436 Lexer.prototype.token = function(src, top, bq) {
55437   var src = src.replace(/^ +$/gm, '')
55438     , next
55439     , loose
55440     , cap
55441     , bull
55442     , b
55443     , item
55444     , space
55445     , i
55446     , l;
55447
55448   while (src) {
55449     // newline
55450     if (cap = this.rules.newline.exec(src)) {
55451       src = src.substring(cap[0].length);
55452       if (cap[0].length > 1) {
55453         this.tokens.push({
55454           type: 'space'
55455         });
55456       }
55457     }
55458
55459     // code
55460     if (cap = this.rules.code.exec(src)) {
55461       src = src.substring(cap[0].length);
55462       cap = cap[0].replace(/^ {4}/gm, '');
55463       this.tokens.push({
55464         type: 'code',
55465         text: !this.options.pedantic
55466           ? cap.replace(/\n+$/, '')
55467           : cap
55468       });
55469       continue;
55470     }
55471
55472     // fences (gfm)
55473     if (cap = this.rules.fences.exec(src)) {
55474       src = src.substring(cap[0].length);
55475       this.tokens.push({
55476         type: 'code',
55477         lang: cap[2],
55478         text: cap[3] || ''
55479       });
55480       continue;
55481     }
55482
55483     // heading
55484     if (cap = this.rules.heading.exec(src)) {
55485       src = src.substring(cap[0].length);
55486       this.tokens.push({
55487         type: 'heading',
55488         depth: cap[1].length,
55489         text: cap[2]
55490       });
55491       continue;
55492     }
55493
55494     // table no leading pipe (gfm)
55495     if (top && (cap = this.rules.nptable.exec(src))) {
55496       src = src.substring(cap[0].length);
55497
55498       item = {
55499         type: 'table',
55500         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
55501         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
55502         cells: cap[3].replace(/\n$/, '').split('\n')
55503       };
55504
55505       for (i = 0; i < item.align.length; i++) {
55506         if (/^ *-+: *$/.test(item.align[i])) {
55507           item.align[i] = 'right';
55508         } else if (/^ *:-+: *$/.test(item.align[i])) {
55509           item.align[i] = 'center';
55510         } else if (/^ *:-+ *$/.test(item.align[i])) {
55511           item.align[i] = 'left';
55512         } else {
55513           item.align[i] = null;
55514         }
55515       }
55516
55517       for (i = 0; i < item.cells.length; i++) {
55518         item.cells[i] = item.cells[i].split(/ *\| */);
55519       }
55520
55521       this.tokens.push(item);
55522
55523       continue;
55524     }
55525
55526     // lheading
55527     if (cap = this.rules.lheading.exec(src)) {
55528       src = src.substring(cap[0].length);
55529       this.tokens.push({
55530         type: 'heading',
55531         depth: cap[2] === '=' ? 1 : 2,
55532         text: cap[1]
55533       });
55534       continue;
55535     }
55536
55537     // hr
55538     if (cap = this.rules.hr.exec(src)) {
55539       src = src.substring(cap[0].length);
55540       this.tokens.push({
55541         type: 'hr'
55542       });
55543       continue;
55544     }
55545
55546     // blockquote
55547     if (cap = this.rules.blockquote.exec(src)) {
55548       src = src.substring(cap[0].length);
55549
55550       this.tokens.push({
55551         type: 'blockquote_start'
55552       });
55553
55554       cap = cap[0].replace(/^ *> ?/gm, '');
55555
55556       // Pass `top` to keep the current
55557       // "toplevel" state. This is exactly
55558       // how markdown.pl works.
55559       this.token(cap, top, true);
55560
55561       this.tokens.push({
55562         type: 'blockquote_end'
55563       });
55564
55565       continue;
55566     }
55567
55568     // list
55569     if (cap = this.rules.list.exec(src)) {
55570       src = src.substring(cap[0].length);
55571       bull = cap[2];
55572
55573       this.tokens.push({
55574         type: 'list_start',
55575         ordered: bull.length > 1
55576       });
55577
55578       // Get each top-level item.
55579       cap = cap[0].match(this.rules.item);
55580
55581       next = false;
55582       l = cap.length;
55583       i = 0;
55584
55585       for (; i < l; i++) {
55586         item = cap[i];
55587
55588         // Remove the list item's bullet
55589         // so it is seen as the next token.
55590         space = item.length;
55591         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
55592
55593         // Outdent whatever the
55594         // list item contains. Hacky.
55595         if (~item.indexOf('\n ')) {
55596           space -= item.length;
55597           item = !this.options.pedantic
55598             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
55599             : item.replace(/^ {1,4}/gm, '');
55600         }
55601
55602         // Determine whether the next list item belongs here.
55603         // Backpedal if it does not belong in this list.
55604         if (this.options.smartLists && i !== l - 1) {
55605           b = block.bullet.exec(cap[i + 1])[0];
55606           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
55607             src = cap.slice(i + 1).join('\n') + src;
55608             i = l - 1;
55609           }
55610         }
55611
55612         // Determine whether item is loose or not.
55613         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
55614         // for discount behavior.
55615         loose = next || /\n\n(?!\s*$)/.test(item);
55616         if (i !== l - 1) {
55617           next = item.charAt(item.length - 1) === '\n';
55618           if (!loose) loose = next;
55619         }
55620
55621         this.tokens.push({
55622           type: loose
55623             ? 'loose_item_start'
55624             : 'list_item_start'
55625         });
55626
55627         // Recurse.
55628         this.token(item, false, bq);
55629
55630         this.tokens.push({
55631           type: 'list_item_end'
55632         });
55633       }
55634
55635       this.tokens.push({
55636         type: 'list_end'
55637       });
55638
55639       continue;
55640     }
55641
55642     // html
55643     if (cap = this.rules.html.exec(src)) {
55644       src = src.substring(cap[0].length);
55645       this.tokens.push({
55646         type: this.options.sanitize
55647           ? 'paragraph'
55648           : 'html',
55649         pre: !this.options.sanitizer
55650           && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
55651         text: cap[0]
55652       });
55653       continue;
55654     }
55655
55656     // def
55657     if ((!bq && top) && (cap = this.rules.def.exec(src))) {
55658       src = src.substring(cap[0].length);
55659       this.tokens.links[cap[1].toLowerCase()] = {
55660         href: cap[2],
55661         title: cap[3]
55662       };
55663       continue;
55664     }
55665
55666     // table (gfm)
55667     if (top && (cap = this.rules.table.exec(src))) {
55668       src = src.substring(cap[0].length);
55669
55670       item = {
55671         type: 'table',
55672         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
55673         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
55674         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
55675       };
55676
55677       for (i = 0; i < item.align.length; i++) {
55678         if (/^ *-+: *$/.test(item.align[i])) {
55679           item.align[i] = 'right';
55680         } else if (/^ *:-+: *$/.test(item.align[i])) {
55681           item.align[i] = 'center';
55682         } else if (/^ *:-+ *$/.test(item.align[i])) {
55683           item.align[i] = 'left';
55684         } else {
55685           item.align[i] = null;
55686         }
55687       }
55688
55689       for (i = 0; i < item.cells.length; i++) {
55690         item.cells[i] = item.cells[i]
55691           .replace(/^ *\| *| *\| *$/g, '')
55692           .split(/ *\| */);
55693       }
55694
55695       this.tokens.push(item);
55696
55697       continue;
55698     }
55699
55700     // top-level paragraph
55701     if (top && (cap = this.rules.paragraph.exec(src))) {
55702       src = src.substring(cap[0].length);
55703       this.tokens.push({
55704         type: 'paragraph',
55705         text: cap[1].charAt(cap[1].length - 1) === '\n'
55706           ? cap[1].slice(0, -1)
55707           : cap[1]
55708       });
55709       continue;
55710     }
55711
55712     // text
55713     if (cap = this.rules.text.exec(src)) {
55714       // Top-level should never reach here.
55715       src = src.substring(cap[0].length);
55716       this.tokens.push({
55717         type: 'text',
55718         text: cap[0]
55719       });
55720       continue;
55721     }
55722
55723     if (src) {
55724       throw new
55725         Error('Infinite loop on byte: ' + src.charCodeAt(0));
55726     }
55727   }
55728
55729   return this.tokens;
55730 };
55731
55732 /**
55733  * Inline-Level Grammar
55734  */
55735
55736 var inline = {
55737   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
55738   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
55739   url: noop,
55740   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
55741   link: /^!?\[(inside)\]\(href\)/,
55742   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
55743   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
55744   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
55745   em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
55746   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
55747   br: /^ {2,}\n(?!\s*$)/,
55748   del: noop,
55749   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
55750 };
55751
55752 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
55753 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
55754
55755 inline.link = replace(inline.link)
55756   ('inside', inline._inside)
55757   ('href', inline._href)
55758   ();
55759
55760 inline.reflink = replace(inline.reflink)
55761   ('inside', inline._inside)
55762   ();
55763
55764 /**
55765  * Normal Inline Grammar
55766  */
55767
55768 inline.normal = merge({}, inline);
55769
55770 /**
55771  * Pedantic Inline Grammar
55772  */
55773
55774 inline.pedantic = merge({}, inline.normal, {
55775   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
55776   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
55777 });
55778
55779 /**
55780  * GFM Inline Grammar
55781  */
55782
55783 inline.gfm = merge({}, inline.normal, {
55784   escape: replace(inline.escape)('])', '~|])')(),
55785   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
55786   del: /^~~(?=\S)([\s\S]*?\S)~~/,
55787   text: replace(inline.text)
55788     (']|', '~]|')
55789     ('|', '|https?://|')
55790     ()
55791 });
55792
55793 /**
55794  * GFM + Line Breaks Inline Grammar
55795  */
55796
55797 inline.breaks = merge({}, inline.gfm, {
55798   br: replace(inline.br)('{2,}', '*')(),
55799   text: replace(inline.gfm.text)('{2,}', '*')()
55800 });
55801
55802 /**
55803  * Inline Lexer & Compiler
55804  */
55805
55806 function InlineLexer(links, options) {
55807   this.options = options || marked.defaults;
55808   this.links = links;
55809   this.rules = inline.normal;
55810   this.renderer = this.options.renderer || new Renderer;
55811   this.renderer.options = this.options;
55812
55813   if (!this.links) {
55814     throw new
55815       Error('Tokens array requires a `links` property.');
55816   }
55817
55818   if (this.options.gfm) {
55819     if (this.options.breaks) {
55820       this.rules = inline.breaks;
55821     } else {
55822       this.rules = inline.gfm;
55823     }
55824   } else if (this.options.pedantic) {
55825     this.rules = inline.pedantic;
55826   }
55827 }
55828
55829 /**
55830  * Expose Inline Rules
55831  */
55832
55833 InlineLexer.rules = inline;
55834
55835 /**
55836  * Static Lexing/Compiling Method
55837  */
55838
55839 InlineLexer.output = function(src, links, options) {
55840   var inline = new InlineLexer(links, options);
55841   return inline.output(src);
55842 };
55843
55844 /**
55845  * Lexing/Compiling
55846  */
55847
55848 InlineLexer.prototype.output = function(src) {
55849   var out = ''
55850     , link
55851     , text
55852     , href
55853     , cap;
55854
55855   while (src) {
55856     // escape
55857     if (cap = this.rules.escape.exec(src)) {
55858       src = src.substring(cap[0].length);
55859       out += cap[1];
55860       continue;
55861     }
55862
55863     // autolink
55864     if (cap = this.rules.autolink.exec(src)) {
55865       src = src.substring(cap[0].length);
55866       if (cap[2] === '@') {
55867         text = cap[1].charAt(6) === ':'
55868           ? this.mangle(cap[1].substring(7))
55869           : this.mangle(cap[1]);
55870         href = this.mangle('mailto:') + text;
55871       } else {
55872         text = escape(cap[1]);
55873         href = text;
55874       }
55875       out += this.renderer.link(href, null, text);
55876       continue;
55877     }
55878
55879     // url (gfm)
55880     if (!this.inLink && (cap = this.rules.url.exec(src))) {
55881       src = src.substring(cap[0].length);
55882       text = escape(cap[1]);
55883       href = text;
55884       out += this.renderer.link(href, null, text);
55885       continue;
55886     }
55887
55888     // tag
55889     if (cap = this.rules.tag.exec(src)) {
55890       if (!this.inLink && /^<a /i.test(cap[0])) {
55891         this.inLink = true;
55892       } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
55893         this.inLink = false;
55894       }
55895       src = src.substring(cap[0].length);
55896       out += this.options.sanitize
55897         ? this.options.sanitizer
55898           ? this.options.sanitizer(cap[0])
55899           : escape(cap[0])
55900         : cap[0];
55901       continue;
55902     }
55903
55904     // link
55905     if (cap = this.rules.link.exec(src)) {
55906       src = src.substring(cap[0].length);
55907       this.inLink = true;
55908       out += this.outputLink(cap, {
55909         href: cap[2],
55910         title: cap[3]
55911       });
55912       this.inLink = false;
55913       continue;
55914     }
55915
55916     // reflink, nolink
55917     if ((cap = this.rules.reflink.exec(src))
55918         || (cap = this.rules.nolink.exec(src))) {
55919       src = src.substring(cap[0].length);
55920       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
55921       link = this.links[link.toLowerCase()];
55922       if (!link || !link.href) {
55923         out += cap[0].charAt(0);
55924         src = cap[0].substring(1) + src;
55925         continue;
55926       }
55927       this.inLink = true;
55928       out += this.outputLink(cap, link);
55929       this.inLink = false;
55930       continue;
55931     }
55932
55933     // strong
55934     if (cap = this.rules.strong.exec(src)) {
55935       src = src.substring(cap[0].length);
55936       out += this.renderer.strong(this.output(cap[2] || cap[1]));
55937       continue;
55938     }
55939
55940     // em
55941     if (cap = this.rules.em.exec(src)) {
55942       src = src.substring(cap[0].length);
55943       out += this.renderer.em(this.output(cap[2] || cap[1]));
55944       continue;
55945     }
55946
55947     // code
55948     if (cap = this.rules.code.exec(src)) {
55949       src = src.substring(cap[0].length);
55950       out += this.renderer.codespan(escape(cap[2], true));
55951       continue;
55952     }
55953
55954     // br
55955     if (cap = this.rules.br.exec(src)) {
55956       src = src.substring(cap[0].length);
55957       out += this.renderer.br();
55958       continue;
55959     }
55960
55961     // del (gfm)
55962     if (cap = this.rules.del.exec(src)) {
55963       src = src.substring(cap[0].length);
55964       out += this.renderer.del(this.output(cap[1]));
55965       continue;
55966     }
55967
55968     // text
55969     if (cap = this.rules.text.exec(src)) {
55970       src = src.substring(cap[0].length);
55971       out += this.renderer.text(escape(this.smartypants(cap[0])));
55972       continue;
55973     }
55974
55975     if (src) {
55976       throw new
55977         Error('Infinite loop on byte: ' + src.charCodeAt(0));
55978     }
55979   }
55980
55981   return out;
55982 };
55983
55984 /**
55985  * Compile Link
55986  */
55987
55988 InlineLexer.prototype.outputLink = function(cap, link) {
55989   var href = escape(link.href)
55990     , title = link.title ? escape(link.title) : null;
55991
55992   return cap[0].charAt(0) !== '!'
55993     ? this.renderer.link(href, title, this.output(cap[1]))
55994     : this.renderer.image(href, title, escape(cap[1]));
55995 };
55996
55997 /**
55998  * Smartypants Transformations
55999  */
56000
56001 InlineLexer.prototype.smartypants = function(text) {
56002   if (!this.options.smartypants) return text;
56003   return text
56004     // em-dashes
56005     .replace(/---/g, '\u2014')
56006     // en-dashes
56007     .replace(/--/g, '\u2013')
56008     // opening singles
56009     .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
56010     // closing singles & apostrophes
56011     .replace(/'/g, '\u2019')
56012     // opening doubles
56013     .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
56014     // closing doubles
56015     .replace(/"/g, '\u201d')
56016     // ellipses
56017     .replace(/\.{3}/g, '\u2026');
56018 };
56019
56020 /**
56021  * Mangle Links
56022  */
56023
56024 InlineLexer.prototype.mangle = function(text) {
56025   if (!this.options.mangle) return text;
56026   var out = ''
56027     , l = text.length
56028     , i = 0
56029     , ch;
56030
56031   for (; i < l; i++) {
56032     ch = text.charCodeAt(i);
56033     if (Math.random() > 0.5) {
56034       ch = 'x' + ch.toString(16);
56035     }
56036     out += '&#' + ch + ';';
56037   }
56038
56039   return out;
56040 };
56041
56042 /**
56043  * Renderer
56044  */
56045
56046 function Renderer(options) {
56047   this.options = options || {};
56048 }
56049
56050 Renderer.prototype.code = function(code, lang, escaped) {
56051   if (this.options.highlight) {
56052     var out = this.options.highlight(code, lang);
56053     if (out != null && out !== code) {
56054       escaped = true;
56055       code = out;
56056     }
56057   }
56058
56059   if (!lang) {
56060     return '<pre><code>'
56061       + (escaped ? code : escape(code, true))
56062       + '\n</code></pre>';
56063   }
56064
56065   return '<pre><code class="'
56066     + this.options.langPrefix
56067     + escape(lang, true)
56068     + '">'
56069     + (escaped ? code : escape(code, true))
56070     + '\n</code></pre>\n';
56071 };
56072
56073 Renderer.prototype.blockquote = function(quote) {
56074   return '<blockquote>\n' + quote + '</blockquote>\n';
56075 };
56076
56077 Renderer.prototype.html = function(html) {
56078   return html;
56079 };
56080
56081 Renderer.prototype.heading = function(text, level, raw) {
56082   return '<h'
56083     + level
56084     + ' id="'
56085     + this.options.headerPrefix
56086     + raw.toLowerCase().replace(/[^\w]+/g, '-')
56087     + '">'
56088     + text
56089     + '</h'
56090     + level
56091     + '>\n';
56092 };
56093
56094 Renderer.prototype.hr = function() {
56095   return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
56096 };
56097
56098 Renderer.prototype.list = function(body, ordered) {
56099   var type = ordered ? 'ol' : 'ul';
56100   return '<' + type + '>\n' + body + '</' + type + '>\n';
56101 };
56102
56103 Renderer.prototype.listitem = function(text) {
56104   return '<li>' + text + '</li>\n';
56105 };
56106
56107 Renderer.prototype.paragraph = function(text) {
56108   return '<p>' + text + '</p>\n';
56109 };
56110
56111 Renderer.prototype.table = function(header, body) {
56112   return '<table>\n'
56113     + '<thead>\n'
56114     + header
56115     + '</thead>\n'
56116     + '<tbody>\n'
56117     + body
56118     + '</tbody>\n'
56119     + '</table>\n';
56120 };
56121
56122 Renderer.prototype.tablerow = function(content) {
56123   return '<tr>\n' + content + '</tr>\n';
56124 };
56125
56126 Renderer.prototype.tablecell = function(content, flags) {
56127   var type = flags.header ? 'th' : 'td';
56128   var tag = flags.align
56129     ? '<' + type + ' style="text-align:' + flags.align + '">'
56130     : '<' + type + '>';
56131   return tag + content + '</' + type + '>\n';
56132 };
56133
56134 // span level renderer
56135 Renderer.prototype.strong = function(text) {
56136   return '<strong>' + text + '</strong>';
56137 };
56138
56139 Renderer.prototype.em = function(text) {
56140   return '<em>' + text + '</em>';
56141 };
56142
56143 Renderer.prototype.codespan = function(text) {
56144   return '<code>' + text + '</code>';
56145 };
56146
56147 Renderer.prototype.br = function() {
56148   return this.options.xhtml ? '<br/>' : '<br>';
56149 };
56150
56151 Renderer.prototype.del = function(text) {
56152   return '<del>' + text + '</del>';
56153 };
56154
56155 Renderer.prototype.link = function(href, title, text) {
56156   if (this.options.sanitize) {
56157     try {
56158       var prot = decodeURIComponent(unescape(href))
56159         .replace(/[^\w:]/g, '')
56160         .toLowerCase();
56161     } catch (e) {
56162       return '';
56163     }
56164     if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
56165       return '';
56166     }
56167   }
56168   var out = '<a href="' + href + '"';
56169   if (title) {
56170     out += ' title="' + title + '"';
56171   }
56172   out += '>' + text + '</a>';
56173   return out;
56174 };
56175
56176 Renderer.prototype.image = function(href, title, text) {
56177   var out = '<img src="' + href + '" alt="' + text + '"';
56178   if (title) {
56179     out += ' title="' + title + '"';
56180   }
56181   out += this.options.xhtml ? '/>' : '>';
56182   return out;
56183 };
56184
56185 Renderer.prototype.text = function(text) {
56186   return text;
56187 };
56188
56189 /**
56190  * Parsing & Compiling
56191  */
56192
56193 function Parser(options) {
56194   this.tokens = [];
56195   this.token = null;
56196   this.options = options || marked.defaults;
56197   this.options.renderer = this.options.renderer || new Renderer;
56198   this.renderer = this.options.renderer;
56199   this.renderer.options = this.options;
56200 }
56201
56202 /**
56203  * Static Parse Method
56204  */
56205
56206 Parser.parse = function(src, options, renderer) {
56207   var parser = new Parser(options, renderer);
56208   return parser.parse(src);
56209 };
56210
56211 /**
56212  * Parse Loop
56213  */
56214
56215 Parser.prototype.parse = function(src) {
56216   this.inline = new InlineLexer(src.links, this.options, this.renderer);
56217   this.tokens = src.reverse();
56218
56219   var out = '';
56220   while (this.next()) {
56221     out += this.tok();
56222   }
56223
56224   return out;
56225 };
56226
56227 /**
56228  * Next Token
56229  */
56230
56231 Parser.prototype.next = function() {
56232   return this.token = this.tokens.pop();
56233 };
56234
56235 /**
56236  * Preview Next Token
56237  */
56238
56239 Parser.prototype.peek = function() {
56240   return this.tokens[this.tokens.length - 1] || 0;
56241 };
56242
56243 /**
56244  * Parse Text Tokens
56245  */
56246
56247 Parser.prototype.parseText = function() {
56248   var body = this.token.text;
56249
56250   while (this.peek().type === 'text') {
56251     body += '\n' + this.next().text;
56252   }
56253
56254   return this.inline.output(body);
56255 };
56256
56257 /**
56258  * Parse Current Token
56259  */
56260
56261 Parser.prototype.tok = function() {
56262   switch (this.token.type) {
56263     case 'space': {
56264       return '';
56265     }
56266     case 'hr': {
56267       return this.renderer.hr();
56268     }
56269     case 'heading': {
56270       return this.renderer.heading(
56271         this.inline.output(this.token.text),
56272         this.token.depth,
56273         this.token.text);
56274     }
56275     case 'code': {
56276       return this.renderer.code(this.token.text,
56277         this.token.lang,
56278         this.token.escaped);
56279     }
56280     case 'table': {
56281       var header = ''
56282         , body = ''
56283         , i
56284         , row
56285         , cell
56286         , flags
56287         , j;
56288
56289       // header
56290       cell = '';
56291       for (i = 0; i < this.token.header.length; i++) {
56292         flags = { header: true, align: this.token.align[i] };
56293         cell += this.renderer.tablecell(
56294           this.inline.output(this.token.header[i]),
56295           { header: true, align: this.token.align[i] }
56296         );
56297       }
56298       header += this.renderer.tablerow(cell);
56299
56300       for (i = 0; i < this.token.cells.length; i++) {
56301         row = this.token.cells[i];
56302
56303         cell = '';
56304         for (j = 0; j < row.length; j++) {
56305           cell += this.renderer.tablecell(
56306             this.inline.output(row[j]),
56307             { header: false, align: this.token.align[j] }
56308           );
56309         }
56310
56311         body += this.renderer.tablerow(cell);
56312       }
56313       return this.renderer.table(header, body);
56314     }
56315     case 'blockquote_start': {
56316       var body = '';
56317
56318       while (this.next().type !== 'blockquote_end') {
56319         body += this.tok();
56320       }
56321
56322       return this.renderer.blockquote(body);
56323     }
56324     case 'list_start': {
56325       var body = ''
56326         , ordered = this.token.ordered;
56327
56328       while (this.next().type !== 'list_end') {
56329         body += this.tok();
56330       }
56331
56332       return this.renderer.list(body, ordered);
56333     }
56334     case 'list_item_start': {
56335       var body = '';
56336
56337       while (this.next().type !== 'list_item_end') {
56338         body += this.token.type === 'text'
56339           ? this.parseText()
56340           : this.tok();
56341       }
56342
56343       return this.renderer.listitem(body);
56344     }
56345     case 'loose_item_start': {
56346       var body = '';
56347
56348       while (this.next().type !== 'list_item_end') {
56349         body += this.tok();
56350       }
56351
56352       return this.renderer.listitem(body);
56353     }
56354     case 'html': {
56355       var html = !this.token.pre && !this.options.pedantic
56356         ? this.inline.output(this.token.text)
56357         : this.token.text;
56358       return this.renderer.html(html);
56359     }
56360     case 'paragraph': {
56361       return this.renderer.paragraph(this.inline.output(this.token.text));
56362     }
56363     case 'text': {
56364       return this.renderer.paragraph(this.parseText());
56365     }
56366   }
56367 };
56368
56369 /**
56370  * Helpers
56371  */
56372
56373 function escape(html, encode) {
56374   return html
56375     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
56376     .replace(/</g, '&lt;')
56377     .replace(/>/g, '&gt;')
56378     .replace(/"/g, '&quot;')
56379     .replace(/'/g, '&#39;');
56380 }
56381
56382 function unescape(html) {
56383         // explicitly match decimal, hex, and named HTML entities 
56384   return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
56385     n = n.toLowerCase();
56386     if (n === 'colon') return ':';
56387     if (n.charAt(0) === '#') {
56388       return n.charAt(1) === 'x'
56389         ? String.fromCharCode(parseInt(n.substring(2), 16))
56390         : String.fromCharCode(+n.substring(1));
56391     }
56392     return '';
56393   });
56394 }
56395
56396 function replace(regex, opt) {
56397   regex = regex.source;
56398   opt = opt || '';
56399   return function self(name, val) {
56400     if (!name) return new RegExp(regex, opt);
56401     val = val.source || val;
56402     val = val.replace(/(^|[^\[])\^/g, '$1');
56403     regex = regex.replace(name, val);
56404     return self;
56405   };
56406 }
56407
56408 function noop() {}
56409 noop.exec = noop;
56410
56411 function merge(obj) {
56412   var i = 1
56413     , target
56414     , key;
56415
56416   for (; i < arguments.length; i++) {
56417     target = arguments[i];
56418     for (key in target) {
56419       if (Object.prototype.hasOwnProperty.call(target, key)) {
56420         obj[key] = target[key];
56421       }
56422     }
56423   }
56424
56425   return obj;
56426 }
56427
56428
56429 /**
56430  * Marked
56431  */
56432
56433 function marked(src, opt, callback) {
56434   if (callback || typeof opt === 'function') {
56435     if (!callback) {
56436       callback = opt;
56437       opt = null;
56438     }
56439
56440     opt = merge({}, marked.defaults, opt || {});
56441
56442     var highlight = opt.highlight
56443       , tokens
56444       , pending
56445       , i = 0;
56446
56447     try {
56448       tokens = Lexer.lex(src, opt);
56449     } catch (e) {
56450       return callback(e);
56451     }
56452
56453     pending = tokens.length;
56454
56455     var done = function(err) {
56456       if (err) {
56457         opt.highlight = highlight;
56458         return callback(err);
56459       }
56460
56461       var out;
56462
56463       try {
56464         out = Parser.parse(tokens, opt);
56465       } catch (e) {
56466         err = e;
56467       }
56468
56469       opt.highlight = highlight;
56470
56471       return err
56472         ? callback(err)
56473         : callback(null, out);
56474     };
56475
56476     if (!highlight || highlight.length < 3) {
56477       return done();
56478     }
56479
56480     delete opt.highlight;
56481
56482     if (!pending) return done();
56483
56484     for (; i < tokens.length; i++) {
56485       (function(token) {
56486         if (token.type !== 'code') {
56487           return --pending || done();
56488         }
56489         return highlight(token.text, token.lang, function(err, code) {
56490           if (err) return done(err);
56491           if (code == null || code === token.text) {
56492             return --pending || done();
56493           }
56494           token.text = code;
56495           token.escaped = true;
56496           --pending || done();
56497         });
56498       })(tokens[i]);
56499     }
56500
56501     return;
56502   }
56503   try {
56504     if (opt) opt = merge({}, marked.defaults, opt);
56505     return Parser.parse(Lexer.lex(src, opt), opt);
56506   } catch (e) {
56507     e.message += '\nPlease report this to https://github.com/chjj/marked.';
56508     if ((opt || marked.defaults).silent) {
56509       return '<p>An error occured:</p><pre>'
56510         + escape(e.message + '', true)
56511         + '</pre>';
56512     }
56513     throw e;
56514   }
56515 }
56516
56517 /**
56518  * Options
56519  */
56520
56521 marked.options =
56522 marked.setOptions = function(opt) {
56523   merge(marked.defaults, opt);
56524   return marked;
56525 };
56526
56527 marked.defaults = {
56528   gfm: true,
56529   tables: true,
56530   breaks: false,
56531   pedantic: false,
56532   sanitize: false,
56533   sanitizer: null,
56534   mangle: true,
56535   smartLists: false,
56536   silent: false,
56537   highlight: null,
56538   langPrefix: 'lang-',
56539   smartypants: false,
56540   headerPrefix: '',
56541   renderer: new Renderer,
56542   xhtml: false
56543 };
56544
56545 /**
56546  * Expose
56547  */
56548
56549 marked.Parser = Parser;
56550 marked.parser = Parser.parse;
56551
56552 marked.Renderer = Renderer;
56553
56554 marked.Lexer = Lexer;
56555 marked.lexer = Lexer.lex;
56556
56557 marked.InlineLexer = InlineLexer;
56558 marked.inlineLexer = InlineLexer.output;
56559
56560 marked.parse = marked;
56561
56562 if (typeof module !== 'undefined' && typeof exports === 'object') {
56563   module.exports = marked;
56564 } else if (typeof define === 'function' && define.amd) {
56565   define(function() { return marked; });
56566 } else {
56567   this.marked = marked;
56568 }
56569
56570 }).call(function() {
56571   return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
56572 }());
56573 });
56574
56575 // toggles the visibility of ui elements, using a combination of the
56576 // hide class, which sets display=none, and a d3 transition for opacity.
56577 // this will cause blinking when called repeatedly, so check that the
56578 // value actually changes between calls.
56579 function uiToggle(show, callback) {
56580     return function(selection$$1) {
56581         selection$$1
56582             .style('opacity', show ? 0 : 1)
56583             .classed('hide', false)
56584             .transition()
56585             .style('opacity', show ? 1 : 0)
56586             .on('end', function() {
56587                 select(this)
56588                     .classed('hide', !show)
56589                     .style('opacity', null);
56590                 if (callback) callback.apply(this);
56591             });
56592     };
56593 }
56594
56595 // Tooltips and svg mask used to highlight certain features
56596 function d3curtain() {
56597
56598     var dispatch$$1 = dispatch(),
56599         surface = select(null),
56600         tooltip = select(null),
56601         darkness = select(null);
56602
56603     function curtain(selection$$1) {
56604         surface = selection$$1
56605             .append('svg')
56606             .attr('id', 'curtain')
56607             .style('z-index', 1000)
56608             .style('pointer-events', 'none')
56609             .style('position', 'absolute')
56610             .style('top', 0)
56611             .style('left', 0);
56612
56613         darkness = surface.append('path')
56614             .attr('x', 0)
56615             .attr('y', 0)
56616             .attr('class', 'curtain-darkness');
56617
56618         select(window).on('resize.curtain', resize);
56619
56620         tooltip = selection$$1.append('div')
56621             .attr('class', 'tooltip')
56622             .style('z-index', 1002);
56623
56624         tooltip
56625             .append('div')
56626             .attr('class', 'tooltip-arrow');
56627
56628         tooltip
56629             .append('div')
56630             .attr('class', 'tooltip-inner');
56631
56632         resize();
56633
56634
56635         function resize() {
56636             surface
56637                 .attr('width', window.innerWidth)
56638                 .attr('height', window.innerHeight);
56639             curtain.cut(darkness.datum());
56640         }
56641     }
56642
56643
56644     curtain.reveal = function(box, text$$1, tooltipclass, duration) {
56645         if (typeof box === 'string') box = select(box).node();
56646         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
56647
56648         curtain.cut(box, duration);
56649
56650         if (text$$1) {
56651             // pseudo markdown bold text hack
56652             var parts = text$$1.split('**');
56653             var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
56654             if (parts[1]) html$$1 += '<span class="bold">' + parts[1] + '</span>';
56655
56656             var selection$$1 = tooltip
56657                 .classed('in', true)
56658                 .selectAll('.tooltip-inner')
56659                 .html(html$$1);
56660
56661             var dimensions = utilGetDimensions(selection$$1, true),
56662                 w = window.innerWidth,
56663                 h = window.innerHeight,
56664                 side, pos;
56665
56666             // trim box dimensions to just the portion that fits in the window..
56667             if (box.top + box.height > h) {
56668                 box.height -= (box.top + box.height - h);
56669             }
56670             if (box.left + box.width > w) {
56671                 box.width -= (box.left + box.width - w);
56672             }
56673
56674             // determine tooltip placement..
56675             if (box.top + box.height < Math.min(100, box.width + box.left)) {
56676                 side = 'bottom';
56677                 pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top + box.height];
56678
56679             } else if (box.left + box.width + 300 < w) {
56680                 side = 'right';
56681                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
56682
56683             } else if (box.left > 300) {
56684                 side = 'left';
56685                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
56686
56687             } else {
56688                 side = 'bottom';
56689                 pos = [box.left, box.top + box.height];
56690             }
56691
56692             pos = [
56693                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
56694                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
56695             ];
56696
56697             if (duration !== 0 || !tooltip.classed(side)) {
56698                 tooltip.call(uiToggle(true));
56699             }
56700
56701             tooltip
56702                 .style('top', pos[1] + 'px')
56703                 .style('left', pos[0] + 'px')
56704                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass);
56705
56706         } else {
56707             tooltip.call(uiToggle(false));
56708         }
56709     };
56710
56711
56712     curtain.cut = function(datum, duration) {
56713         darkness.datum(datum)
56714             .interrupt();
56715
56716         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
56717             .attr('d', function(d) {
56718                 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
56719                     window.innerWidth + ',' + window.innerHeight + 'L' +
56720                     window.innerWidth + ',0 Z';
56721
56722                 if (!d) return string;
56723                 return string + 'M' +
56724                     d.left + ',' + d.top + 'L' +
56725                     d.left + ',' + (d.top + d.height) + 'L' +
56726                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
56727                     (d.left + d.width) + ',' + (d.top) + 'Z';
56728
56729             });
56730     };
56731
56732
56733     curtain.remove = function() {
56734         surface.remove();
56735         tooltip.remove();
56736     };
56737
56738
56739     return utilRebind(curtain, dispatch$$1, 'on');
56740 }
56741
56742 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"]}};
56743
56744 function pointBox(point, context) {
56745     var rect = context.surfaceRect();
56746     point = context.projection(point);
56747     return {
56748         left: point[0] + rect.left - 30,
56749         top: point[1] + rect.top - 50,
56750         width: 60,
56751         height: 70
56752      };
56753 }
56754
56755
56756 function pad$1(box, padding, context) {
56757     if (box instanceof Array) {
56758         var rect = context.surfaceRect();
56759         box = context.projection(box);
56760         box = {
56761             left: box[0] + rect.left,
56762             top: box[1] + rect.top
56763         };
56764     }
56765     return {
56766         left: box.left - padding,
56767         top: box.top - padding,
56768         width: (box.width || 0) + 2 * padding,
56769         height: (box.width || 0) + 2 * padding
56770     };
56771 }
56772
56773
56774 function icon(name, svgklass) {
56775     return '<svg class="icon ' + (svgklass || '') + '">' +
56776          '<use xlink:href="' + name + '"></use></svg>';
56777  }
56778
56779 function uiIntroNavigation(context, reveal) {
56780     var dispatch$$1 = dispatch('done'),
56781         timeouts = [];
56782
56783     var step = {
56784         title: 'intro.navigation.title'
56785     };
56786
56787
56788     function set$$1(f, t$$1) {
56789         timeouts.push(window.setTimeout(f, t$$1));
56790     }
56791
56792
56793     function eventCancel() {
56794         event.stopPropagation();
56795         event.preventDefault();
56796     }
56797
56798
56799     step.enter = function() {
56800         var rect = context.surfaceRect(),
56801             map$$1 = {
56802                 left: rect.left + 10,
56803                 top: rect.top + 70,
56804                 width: rect.width - 70,
56805                 height: rect.height - 170
56806             };
56807
56808         context.map().centerZoom([-85.63591, 41.94285], 19);
56809
56810         reveal(map$$1, t('intro.navigation.drag'));
56811
56812         context.map().on('move.intro', lodash.debounce(function() {
56813             context.map().on('move.intro', null);
56814             townhall();
56815             context.on('enter.intro', inspectTownHall);
56816         }, 400));
56817
56818
56819         function townhall() {
56820             var hall = [-85.63645945147184, 41.942986488012565];
56821             var point = context.projection(hall);
56822
56823             if (point[0] < 0 || point[0] > rect.width ||
56824                 point[1] < 0 || point[1] > rect.height) {
56825                 context.map().center(hall);
56826             }
56827
56828             var box = pointBox(hall, context);
56829             reveal(box, t('intro.navigation.select'));
56830
56831             context.map().on('move.intro', function() {
56832                 var box = pointBox(hall, context);
56833                 reveal(box, t('intro.navigation.select'), {duration: 0});
56834             });
56835         }
56836
56837
56838         function inspectTownHall(mode) {
56839             if (mode.id !== 'select') return;
56840             context.on('enter.intro', null);
56841             context.map().on('move.intro', null);
56842             set$$1(function() {
56843                 reveal('.entity-editor-pane',
56844                     t('intro.navigation.pane', { button: icon('#icon-close', 'pre-text') }));
56845                 context.on('exit.intro', streetSearch);
56846             }, 700);
56847         }
56848
56849
56850         function streetSearch() {
56851             context.on('exit.intro', null);
56852             reveal('.search-header input',
56853                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
56854             select('.search-header input')
56855                 .on('keyup.intro', searchResult);
56856         }
56857
56858
56859         function searchResult() {
56860             var first = select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
56861                 firstName = first.select('.entity-name'),
56862                 name = t('intro.graph.spring_st');
56863
56864             if (!firstName.empty() && firstName.text() === name) {
56865                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
56866                 context.on('exit.intro', selectedStreet);
56867                 select('.search-header input')
56868                     .on('keydown.intro', eventCancel, true)
56869                     .on('keyup.intro', null);
56870             }
56871         }
56872
56873
56874         function selectedStreet() {
56875             var springSt = [-85.63585099140167, 41.942506848938926];
56876             context.map().center(springSt);
56877             context.on('exit.intro', function() {
56878                 dispatch$$1.call('done');
56879             });
56880
56881             set$$1(function() {
56882                 reveal('.entity-editor-pane',
56883                     t('intro.navigation.chosen', {
56884                         name: t('intro.graph.spring_st'),
56885                         button: icon('#icon-close', 'pre-text')
56886                     }));
56887             }, 400);
56888         }
56889     };
56890
56891
56892     step.exit = function() {
56893         timeouts.forEach(window.clearTimeout);
56894         context.map().on('move.intro', null);
56895         context.on('enter.intro', null);
56896         context.on('exit.intro', null);
56897         select('.search-header input')
56898             .on('keydown.intro', null)
56899             .on('keyup.intro', null);
56900     };
56901
56902
56903     return utilRebind(step, dispatch$$1, 'on');
56904 }
56905
56906 function uiIntroPoint(context, reveal) {
56907     var dispatch$$1 = dispatch('done'),
56908         timeouts = [];
56909
56910     var step = {
56911         title: 'intro.points.title'
56912     };
56913
56914
56915     function setTimeout(f, t$$1) {
56916         timeouts.push(window.setTimeout(f, t$$1));
56917     }
56918
56919
56920     function eventCancel() {
56921         event.stopPropagation();
56922         event.preventDefault();
56923     }
56924
56925
56926     step.enter = function() {
56927         context.map().centerZoom([-85.63279, 41.94394], 19);
56928         reveal('button.add-point',
56929             t('intro.points.add', { button: icon('#icon-point', 'pre-text') }),
56930             { tooltipClass: 'intro-points-add' });
56931
56932         var corner = [-85.632481,41.944094];
56933
56934         context.on('enter.intro', addPoint);
56935
56936
56937         function addPoint(mode) {
56938             if (mode.id !== 'add-point') return;
56939             context.on('enter.intro', enterSelect);
56940
56941             var pointBox$$1 = pad$1(corner, 150, context);
56942             reveal(pointBox$$1, t('intro.points.place'));
56943
56944             context.map().on('move.intro', function() {
56945                 pointBox$$1 = pad$1(corner, 150, context);
56946                 reveal(pointBox$$1, t('intro.points.place'), {duration: 0});
56947             });
56948         }
56949
56950
56951         function enterSelect(mode) {
56952             if (mode.id !== 'select') return;
56953             context.map().on('move.intro', null);
56954             context.on('enter.intro', null);
56955
56956             setTimeout(function() {
56957                 reveal('.preset-search-input',
56958                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
56959                 select('.preset-search-input').on('keyup.intro', keySearch);
56960             }, 500);
56961         }
56962
56963
56964         function keySearch() {
56965             var first = select('.preset-list-item:first-child');
56966             if (first.classed('preset-amenity-cafe')) {
56967                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
56968                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
56969                 select('.preset-search-input')
56970                     .on('keydown.intro', eventCancel, true)
56971                     .on('keyup.intro', null);
56972             }
56973         }
56974
56975
56976         function selectedPreset() {
56977             setTimeout(function() {
56978                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
56979                 context.history().on('change.intro', closeEditor);
56980                 context.on('exit.intro', selectPoint);
56981             }, 400);
56982         }
56983
56984
56985         function closeEditor() {
56986             select('.preset-search-input').on('keydown.intro', null);
56987             context.history().on('change.intro', null);
56988             reveal('.entity-editor-pane',
56989                 t('intro.points.close', { button: icon('#icon-apply', 'pre-text') }));
56990         }
56991
56992
56993         function selectPoint() {
56994             context.on('exit.intro', null);
56995             context.history().on('change.intro', null);
56996             context.on('enter.intro', enterReselect);
56997
56998             var pointBox$$1 = pad$1(corner, 150, context);
56999             reveal(pointBox$$1, t('intro.points.reselect'));
57000
57001             context.map().on('move.intro', function() {
57002                 pointBox$$1 = pad$1(corner, 150, context);
57003                 reveal(pointBox$$1, t('intro.points.reselect'), {duration: 0});
57004             });
57005         }
57006
57007
57008         function enterReselect(mode) {
57009             if (mode.id !== 'select') return;
57010             context.map().on('move.intro', null);
57011             context.on('enter.intro', null);
57012
57013             setTimeout(function() {
57014                 reveal('.entity-editor-pane',
57015                     t('intro.points.fixname', { button: icon('#icon-apply', 'pre-text') }));
57016                 context.on('exit.intro', deletePoint);
57017             }, 500);
57018         }
57019
57020
57021         function deletePoint() {
57022             context.on('exit.intro', null);
57023             context.on('enter.intro', enterDelete);
57024
57025             var pointBox$$1 = pad$1(corner, 150, context);
57026             reveal(pointBox$$1, t('intro.points.reselect_delete'));
57027
57028             context.map().on('move.intro', function() {
57029                 pointBox$$1 = pad$1(corner, 150, context);
57030                 reveal(pointBox$$1, t('intro.points.reselect_delete'), {duration: 0});
57031             });
57032         }
57033
57034
57035         function enterDelete(mode) {
57036             if (mode.id !== 'select') return;
57037             context.map().on('move.intro', null);
57038             context.on('enter.intro', null);
57039             context.on('exit.intro', deletePoint);
57040             context.map().on('move.intro', deletePoint);
57041             context.history().on('change.intro', deleted);
57042
57043             setTimeout(function() {
57044                 var node = select('.radial-menu-item-delete').node();
57045                 var pointBox$$1 = pad$1(node.getBoundingClientRect(), 50, context);
57046                 reveal(pointBox$$1,
57047                     t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
57048             }, 300);
57049         }
57050
57051
57052         function deleted(changed) {
57053             if (changed.deleted().length) {
57054                 dispatch$$1.call('done');
57055             }
57056         }
57057
57058     };
57059
57060
57061     step.exit = function() {
57062         timeouts.forEach(window.clearTimeout);
57063         context.on('exit.intro', null);
57064         context.on('enter.intro', null);
57065         context.map().on('move.intro', null);
57066         context.history().on('change.intro', null);
57067         select('.preset-search-input')
57068             .on('keyup.intro', null)
57069             .on('keydown.intro', null);
57070     };
57071
57072     return utilRebind(step, dispatch$$1, 'on');
57073 }
57074
57075 function uiIntroArea(context, reveal) {
57076     var dispatch$$1 = dispatch('done'),
57077         timeout$$1;
57078
57079     var step = {
57080         title: 'intro.areas.title'
57081     };
57082
57083
57084     step.enter = function() {
57085         var playground = [-85.63552, 41.94159],
57086             corner = [-85.63565411045074, 41.9417715536927];
57087         context.map().centerZoom(playground, 19);
57088         reveal('button.add-area',
57089             t('intro.areas.add', { button: icon('#icon-area', 'pre-text') }),
57090             { tooltipClass: 'intro-areas-add' });
57091
57092         context.on('enter.intro', addArea);
57093
57094
57095         function addArea(mode) {
57096             if (mode.id !== 'add-area') return;
57097             context.on('enter.intro', drawArea);
57098
57099             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
57100             var pointBox$$1 = pad$1(corner, padding, context);
57101             reveal(pointBox$$1, t('intro.areas.corner'));
57102
57103             context.map().on('move.intro', function() {
57104                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
57105                 pointBox$$1 = pad$1(corner, padding, context);
57106                 reveal(pointBox$$1, t('intro.areas.corner'), {duration: 0});
57107             });
57108         }
57109
57110
57111         function drawArea(mode) {
57112             if (mode.id !== 'draw-area') return;
57113             context.on('enter.intro', enterSelect);
57114
57115             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
57116             var pointBox$$1 = pad$1(playground, padding, context);
57117             reveal(pointBox$$1, t('intro.areas.place'));
57118
57119             context.map().on('move.intro', function() {
57120                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
57121                 pointBox$$1 = pad$1(playground, padding, context);
57122                 reveal(pointBox$$1, t('intro.areas.place'), {duration: 0});
57123             });
57124         }
57125
57126
57127         function enterSelect(mode) {
57128             if (mode.id !== 'select') return;
57129             context.map().on('move.intro', null);
57130             context.on('enter.intro', null);
57131
57132             timeout$$1 = setTimeout(function() {
57133                 reveal('.preset-search-input',
57134                     t('intro.areas.search',
57135                     { name: context.presets().item('leisure/playground').name() }));
57136                 select('.preset-search-input').on('keyup.intro', keySearch);
57137             }, 500);
57138         }
57139
57140
57141         function keySearch() {
57142             var first = select('.preset-list-item:first-child');
57143             if (first.classed('preset-leisure-playground')) {
57144                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
57145                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
57146                 select('.preset-search-input').on('keyup.intro', null);
57147             }
57148         }
57149
57150
57151         function selectedPreset() {
57152             reveal('.pane',
57153                 t('intro.areas.describe', { button: icon('#icon-apply', 'pre-text') }));
57154             context.on('exit.intro', function() {
57155                 dispatch$$1.call('done');
57156             });
57157         }
57158     };
57159
57160
57161     step.exit = function() {
57162         window.clearTimeout(timeout$$1);
57163         context.on('enter.intro', null);
57164         context.on('exit.intro', null);
57165         context.history().on('change.intro', null);
57166         context.map().on('move.intro', null);
57167         select('.preset-search-input').on('keyup.intro', null);
57168     };
57169
57170
57171     return utilRebind(step, dispatch$$1, 'on');
57172 }
57173
57174 function uiIntroLine(context, reveal) {
57175     var dispatch$$1 = dispatch('done'),
57176         timeouts = [];
57177
57178     var step = {
57179         title: 'intro.lines.title'
57180     };
57181
57182
57183     function timeout$$1(f, t$$1) {
57184         timeouts.push(window.setTimeout(f, t$$1));
57185     }
57186
57187
57188     function eventCancel() {
57189         event.stopPropagation();
57190         event.preventDefault();
57191     }
57192
57193
57194     step.enter = function() {
57195         var centroid = [-85.62830, 41.95699];
57196         var midpoint = [-85.62975395449628, 41.95787501510204];
57197         var start = [-85.6297754121684, 41.95805253325314];
57198         var intersection = [-85.62974496187628, 41.95742515554585];
57199
57200         context.map().centerZoom(start, 18);
57201         reveal('button.add-line',
57202             t('intro.lines.add', { button: icon('#icon-line', 'pre-text') }),
57203             { tooltipClass: 'intro-lines-add' });
57204
57205         context.on('enter.intro', addLine);
57206
57207
57208         function addLine(mode) {
57209             if (mode.id !== 'add-line') return;
57210             context.on('enter.intro', drawLine);
57211
57212             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
57213             var pointBox$$1 = pad$1(start, padding, context);
57214             reveal(pointBox$$1, t('intro.lines.start'));
57215
57216             context.map().on('move.intro', function() {
57217                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
57218                 pointBox$$1 = pad$1(start, padding, context);
57219                 reveal(pointBox$$1, t('intro.lines.start'), {duration: 0});
57220             });
57221         }
57222
57223
57224         function drawLine(mode) {
57225             if (mode.id !== 'draw-line') return;
57226             context.history().on('change.intro', addIntersection);
57227             context.on('enter.intro', retry);
57228
57229             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
57230             var pointBox$$1 = pad$1(midpoint, padding, context);
57231             reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
57232
57233             context.map().on('move.intro', function() {
57234                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
57235                 pointBox$$1 = pad$1(midpoint, padding, context);
57236                 reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
57237             });
57238         }
57239
57240
57241         // ended line before creating intersection
57242         function retry(mode) {
57243             if (mode.id !== 'select') return;
57244             var pointBox$$1 = pad$1(intersection, 30, context),
57245                 ids = mode.selectedIDs();
57246             reveal(pointBox$$1, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
57247             select(window).on('mousedown.intro', eventCancel, true);
57248
57249             timeout$$1(function() {
57250                 context.replace(actionDeleteMultiple(ids));
57251                 step.exit();
57252                 step.enter();
57253             }, 3000);
57254         }
57255
57256
57257         function addIntersection(changes) {
57258             if ( lodash.some(changes.created(), function(d) {
57259                 return d.type === 'node' && context.graph().parentWays(d).length > 1;
57260             })) {
57261                 context.history().on('change.intro', null);
57262                 context.on('enter.intro', enterSelect);
57263
57264                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
57265                 var pointBox$$1 = pad$1(centroid, padding, context);
57266                 reveal(pointBox$$1, t('intro.lines.finish'));
57267
57268                 context.map().on('move.intro', function() {
57269                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
57270                     pointBox$$1 = pad$1(centroid, padding, context);
57271                     reveal(pointBox$$1, t('intro.lines.finish'), {duration: 0});
57272                 });
57273             }
57274         }
57275
57276
57277         function enterSelect(mode) {
57278             if (mode.id !== 'select') return;
57279             context.map().on('move.intro', null);
57280             context.on('enter.intro', null);
57281             select('#curtain').style('pointer-events', 'all');
57282
57283             presetCategory();
57284         }
57285
57286
57287         function presetCategory() {
57288             timeout$$1(function() {
57289                 select('#curtain').style('pointer-events', 'none');
57290                 var road = select('.preset-category-road .preset-list-button');
57291                 reveal(road.node(), t('intro.lines.road'));
57292                 utilBindOnce(road, 'click.intro', roadCategory);
57293             }, 500);
57294         }
57295
57296
57297         function roadCategory() {
57298             timeout$$1(function() {
57299                 var grid = select('.subgrid');
57300                 reveal(grid.node(), t('intro.lines.residential'));
57301                 utilBindOnce(grid.selectAll(':not(.preset-highway-residential) .preset-list-button'),
57302                     'click.intro', retryPreset);
57303                 utilBindOnce(grid.selectAll('.preset-highway-residential .preset-list-button'),
57304                     'click.intro', roadDetails);
57305             }, 500);
57306         }
57307
57308
57309         // selected wrong road type
57310         function retryPreset() {
57311             timeout$$1(function() {
57312                 var preset = select('.entity-editor-pane .preset-list-button');
57313                 reveal(preset.node(), t('intro.lines.wrong_preset'));
57314                 utilBindOnce(preset, 'click.intro', presetCategory);
57315             }, 500);
57316         }
57317
57318
57319         function roadDetails() {
57320             reveal('.pane',
57321                 t('intro.lines.describe', { button: icon('#icon-apply', 'pre-text') }));
57322             context.on('exit.intro', function() {
57323                 dispatch$$1.call('done');
57324             });
57325         }
57326     };
57327
57328
57329     step.exit = function() {
57330         select(window).on('mousedown.intro', null, true);
57331         select('#curtain').style('pointer-events', 'none');
57332         timeouts.forEach(window.clearTimeout);
57333         context.on('enter.intro', null);
57334         context.on('exit.intro', null);
57335         context.map().on('move.intro', null);
57336         context.history().on('change.intro', null);
57337     };
57338
57339     return utilRebind(step, dispatch$$1, 'on');
57340 }
57341
57342 function uiIntroStartEditing(context, reveal) {
57343     var dispatch$$1 = dispatch('done', 'startEditing'),
57344         modalSelection,
57345         timeouts = [];
57346
57347     var step = {
57348         title: 'intro.startediting.title'
57349     };
57350
57351
57352     function timeout$$1(f, t$$1) {
57353         timeouts.push(window.setTimeout(f, t$$1));
57354     }
57355
57356
57357     step.enter = function() {
57358         reveal('.map-control.help-control',
57359             t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }));
57360
57361         timeout$$1(function() {
57362             reveal('#bar button.save', t('intro.startediting.save'));
57363         }, 5000);
57364
57365         timeout$$1(function() {
57366             reveal('#surface');
57367         }, 10000);
57368
57369         timeout$$1(function() {
57370             modalSelection = uiModal(context.container());
57371
57372             modalSelection.select('.modal')
57373                 .attr('class', 'modal-splash modal col6');
57374
57375             modalSelection.selectAll('.close').remove();
57376
57377             var startbutton = modalSelection.select('.content')
57378                 .attr('class', 'fillL')
57379                 .append('button')
57380                     .attr('class', 'modal-section huge-modal-button')
57381                     .on('click', function() {
57382                         modalSelection.remove();
57383                     });
57384
57385                 startbutton
57386                     .append('div')
57387                     .attr('class','illustration');
57388
57389                 startbutton
57390                     .append('h2')
57391                     .text(t('intro.startediting.start'));
57392
57393             dispatch$$1.call('startEditing');
57394         }, 10500);
57395     };
57396
57397
57398     step.exit = function() {
57399         if (modalSelection) { modalSelection.remove(); }
57400         timeouts.forEach(window.clearTimeout);
57401     };
57402
57403
57404     return utilRebind(step, dispatch$$1, 'on');
57405 }
57406
57407 var sampleIntros = {
57408     navigation: uiIntroNavigation,
57409     point: uiIntroPoint,
57410     area: uiIntroArea,
57411     line: uiIntroLine,
57412     startEditing: uiIntroStartEditing
57413 };
57414
57415
57416 function uiIntro(context) {
57417     var step;
57418
57419     function localizedName(id) {
57420         var features = {
57421             n2140018997: 'city_hall',
57422             n367813436: 'fire_department',
57423             w203988286: 'memory_isle_park',
57424             w203972937: 'riverwalk_trail',
57425             w203972938: 'riverwalk_trail',
57426             w203972940: 'riverwalk_trail',
57427             w41785752: 'w_michigan_ave',
57428             w134150789: 'w_michigan_ave',
57429             w134150795: 'w_michigan_ave',
57430             w134150800: 'w_michigan_ave',
57431             w134150811: 'w_michigan_ave',
57432             w134150802: 'e_michigan_ave',
57433             w134150836: 'e_michigan_ave',
57434             w41074896: 'e_michigan_ave',
57435             w17965834: 'spring_st',
57436             w203986457: 'scidmore_park',
57437             w203049587: 'petting_zoo',
57438             w17967397: 'n_andrews_st',
57439             w17967315: 's_andrews_st',
57440             w17967326: 'n_constantine_st',
57441             w17966400: 's_constantine_st',
57442             w170848823: 'rocky_river',
57443             w170848824: 'rocky_river',
57444             w170848331: 'rocky_river',
57445             w17967752: 'railroad_dr',
57446             w17965998: 'conrail_rr',
57447             w134150845: 'conrail_rr',
57448             w170989131: 'st_joseph_river',
57449             w143497377: 'n_main_st',
57450             w134150801: 's_main_st',
57451             w134150830: 's_main_st',
57452             w17966462: 's_main_st',
57453             w17967734: 'water_st',
57454             w17964996: 'foster_st',
57455             w170848330: 'portage_river',
57456             w17965351: 'flower_st',
57457             w17965502: 'elm_st',
57458             w17965402: 'walnut_st',
57459             w17964793: 'morris_ave',
57460             w17967444: 'east_st',
57461             w17966984: 'portage_ave'
57462         };
57463
57464         return features[id] && t('intro.graph.' + features[id]);
57465     }
57466
57467
57468     var introGraph = {};
57469
57470     for (var key in dataIntroGraph) {
57471         introGraph[key] = osmEntity$$1(dataIntroGraph[key]);
57472         var name = localizedName(key);
57473         if (name) {
57474             introGraph[key].tags.name = name;
57475         }
57476     }
57477
57478
57479     function intro(selection$$1) {
57480         context.enter(modeBrowse$$1(context));
57481
57482         // Save current map state
57483         var history = context.history().toJSON(),
57484             hash = window.location.hash,
57485             center = context.map().center(),
57486             zoom$$1 = context.map().zoom(),
57487             background = context.background().baseLayerSource(),
57488             opacity = selectAll('#map .layer-background').style('opacity'),
57489             loadedTiles = context.connection().loadedTiles(),
57490             baseEntities = context.history().graph().base().entities;
57491
57492         // Block saving
57493         context.inIntro(true);
57494
57495         // Load semi-real data used in intro
57496         context.connection().toggle(false).reset();
57497         context.history().reset();
57498
57499         context.history().merge(values(coreGraph$$1().load(introGraph).entities));
57500         context.background().bing();
57501
57502         selectAll('#map .layer-background').style('opacity', 1);
57503
57504         var curtain = d3curtain();
57505         selection$$1.call(curtain);
57506
57507
57508         function reveal(box, text$$1, options) {
57509             options = options || {};
57510             curtain.reveal(box,
57511                 text$$1 || '',
57512                 options.tooltipClass || '',
57513                 options.duration
57514             );
57515         }
57516
57517         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
57518             var s = sampleIntros[step](context, reveal)
57519                 .on('done', function() {
57520                     entered.filter(function(d) {
57521                         return d.title === s.title;
57522                     }).classed('finished', true);
57523                     enter(steps[i + 1]);
57524                 });
57525             return s;
57526         });
57527
57528         steps[steps.length - 1].on('startEditing', function() {
57529             curtain.remove();
57530             navwrap.remove();
57531             selectAll('#map .layer-background').style('opacity', opacity);
57532             context.connection().toggle(true).reset().loadedTiles(loadedTiles);
57533             context.history().reset().merge(values(baseEntities));
57534             context.background().baseLayerSource(background);
57535             if (history) context.history().fromJSON(history, false);
57536             context.map().centerZoom(center, zoom$$1);
57537             window.location.replace(hash);
57538             context.inIntro(false);
57539         });
57540
57541         var navwrap = selection$$1
57542             .append('div')
57543             .attr('class', 'intro-nav-wrap fillD');
57544
57545         var buttonwrap = navwrap
57546             .append('div')
57547             .attr('class', 'joined')
57548             .selectAll('button.step');
57549
57550         var entered = buttonwrap
57551             .data(steps)
57552             .enter()
57553             .append('button')
57554             .attr('class', 'step')
57555             .on('click', enter);
57556
57557         entered
57558             .append('label')
57559             .text(function(d) { return t(d.title); });
57560
57561         entered
57562             .append('span')
57563             .attr('class', 'status')
57564             .text(' - ' + t('intro.done'));
57565
57566         enter(steps[0]);
57567
57568
57569         function enter(newStep) {
57570             if (step) { step.exit(); }
57571
57572             context.enter(modeBrowse$$1(context));
57573
57574             step = newStep;
57575             step.enter();
57576
57577             entered.classed('active', function(d) {
57578                 return d.title === step.title;
57579             });
57580         }
57581
57582     }
57583
57584
57585     return intro;
57586 }
57587
57588 function uiHelp(context) {
57589     var key = 'H';
57590
57591     var docKeys = [
57592         'help.help',
57593         'help.editing_saving',
57594         'help.roads',
57595         'help.gps',
57596         'help.imagery',
57597         'help.addresses',
57598         'help.inspector',
57599         'help.buildings',
57600         'help.relations'];
57601
57602     var docs = docKeys.map(function(key) {
57603         var text$$1 = t(key);
57604         return {
57605             title: text$$1.split('\n')[0].replace('#', '').trim(),
57606             html: marked(text$$1.split('\n').slice(1).join('\n'))
57607         };
57608     });
57609
57610
57611     function help(selection$$1) {
57612
57613         function hide() {
57614             setVisible(false);
57615         }
57616
57617
57618         function toggle() {
57619             if (event) event.preventDefault();
57620             tooltipBehavior.hide(button);
57621             setVisible(!button.classed('active'));
57622         }
57623
57624
57625         function setVisible(show) {
57626             if (show !== shown) {
57627                 button.classed('active', show);
57628                 shown = show;
57629
57630                 if (show) {
57631                     selection$$1.on('mousedown.help-inside', function() {
57632                         return event.stopPropagation();
57633                     });
57634                     pane.style('display', 'block')
57635                         .style('right', '-500px')
57636                         .transition()
57637                         .duration(200)
57638                         .style('right', '0px');
57639                 } else {
57640                     pane.style('right', '0px')
57641                         .transition()
57642                         .duration(200)
57643                         .style('right', '-500px')
57644                         .on('end', function() {
57645                             select(this).style('display', 'none');
57646                         });
57647                     selection$$1.on('mousedown.help-inside', null);
57648                 }
57649             }
57650         }
57651
57652
57653         function clickHelp(d, i) {
57654             pane.property('scrollTop', 0);
57655             doctitle.html(d.title);
57656             body.html(d.html);
57657             body.selectAll('a')
57658                 .attr('target', '_blank');
57659             menuItems.classed('selected', function(m) {
57660                 return m.title === d.title;
57661             });
57662
57663             nav.html('');
57664
57665             if (i > 0) {
57666                 var prevLink = nav.append('a')
57667                     .attr('class', 'previous')
57668                     .on('click', function() {
57669                         clickHelp(docs[i - 1], i - 1);
57670                     });
57671                 prevLink.append('span').html('&#9668; ' + docs[i - 1].title);
57672             }
57673             if (i < docs.length - 1) {
57674                 var nextLink = nav.append('a')
57675                     .attr('class', 'next')
57676                     .on('click', function() {
57677                         clickHelp(docs[i + 1], i + 1);
57678                     });
57679                 nextLink.append('span').html(docs[i + 1].title + ' &#9658;');
57680             }
57681         }
57682
57683
57684         function clickWalkthrough() {
57685             select(document.body).call(uiIntro(context));
57686             setVisible(false);
57687         }
57688
57689
57690         var pane = selection$$1.append('div')
57691                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
57692             tooltipBehavior = tooltip()
57693                 .placement((textDirection === 'rtl') ? 'right' : 'left')
57694                 .html(true)
57695                 .title(uiTooltipHtml(t('help.title'), key)),
57696             button = selection$$1.append('button')
57697                 .attr('tabindex', -1)
57698                 .on('click', toggle)
57699                 .call(svgIcon('#icon-help', 'light'))
57700                 .call(tooltipBehavior),
57701             shown = false;
57702
57703
57704         var toc = pane.append('ul')
57705             .attr('class', 'toc');
57706
57707         var menuItems = toc.selectAll('li')
57708             .data(docs)
57709             .enter()
57710             .append('li')
57711             .append('a')
57712             .html(function(d) { return d.title; })
57713             .on('click', clickHelp);
57714
57715         toc.append('li')
57716             .attr('class','walkthrough')
57717             .append('a')
57718             .text(t('splash.walkthrough'))
57719             .on('click', clickWalkthrough);
57720
57721         var content = pane.append('div')
57722             .attr('class', 'left-content');
57723
57724         var doctitle = content.append('h2')
57725             .text(t('help.title'));
57726
57727         var body = content.append('div')
57728             .attr('class', 'body');
57729
57730         var nav = content.append('div')
57731             .attr('class', 'nav');
57732
57733         clickHelp(docs[0], 0);
57734
57735         var keybinding = d3keybinding('help')
57736             .on(key, toggle)
57737             .on('B', hide)
57738             .on('F', hide);
57739
57740         select(document)
57741             .call(keybinding);
57742
57743         context.surface().on('mousedown.help-outside', hide);
57744         context.container().on('mousedown.help-outside', hide);
57745     }
57746
57747     return help;
57748 }
57749
57750 function uiInfo(context) {
57751     var key = uiCmd('⌘I'),
57752         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
57753         isHidden = true;
57754
57755
57756     function info(selection$$1) {
57757
57758         function radiansToMeters(r) {
57759             // using WGS84 authalic radius (6371007.1809 m)
57760             return r * 6371007.1809;
57761         }
57762
57763         function steradiansToSqmeters(r) {
57764             // http://gis.stackexchange.com/a/124857/40446
57765             return r / (4 * Math.PI) * 510065621724000;
57766         }
57767
57768
57769         function toLineString(feature) {
57770             if (feature.type === 'LineString') return feature;
57771
57772             var result = { type: 'LineString', coordinates: [] };
57773             if (feature.type === 'Polygon') {
57774                 result.coordinates = feature.coordinates[0];
57775             } else if (feature.type === 'MultiPolygon') {
57776                 result.coordinates = feature.coordinates[0][0];
57777             }
57778
57779             return result;
57780         }
57781
57782
57783         function displayLength(m) {
57784             var d = m * (isImperial ? 3.28084 : 1),
57785                 p, unit;
57786
57787             if (isImperial) {
57788                 if (d >= 5280) {
57789                     d /= 5280;
57790                     unit = 'mi';
57791                 } else {
57792                     unit = 'ft';
57793                 }
57794             } else {
57795                 if (d >= 1000) {
57796                     d /= 1000;
57797                     unit = 'km';
57798                 } else {
57799                     unit = 'm';
57800                 }
57801             }
57802
57803             // drop unnecessary precision
57804             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
57805
57806             return String(d.toFixed(p)) + ' ' + unit;
57807         }
57808
57809
57810         function displayArea(m2) {
57811             var d = m2 * (isImperial ? 10.7639111056 : 1),
57812                 d1, d2, p1, p2, unit1, unit2;
57813
57814             if (isImperial) {
57815                 if (d >= 6969600) {     // > 0.25mi² show mi²
57816                     d1 = d / 27878400;
57817                     unit1 = 'mi²';
57818                 } else {
57819                     d1 = d;
57820                     unit1 = 'ft²';
57821                 }
57822
57823                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
57824                     d2 = d / 43560;
57825                     unit2 = 'ac';
57826                 }
57827
57828             } else {
57829                 if (d >= 250000) {    // > 0.25km² show km²
57830                     d1 = d / 1000000;
57831                     unit1 = 'km²';
57832                 } else {
57833                     d1 = d;
57834                     unit1 = 'm²';
57835                 }
57836
57837                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
57838                     d2 = d / 10000;
57839                     unit2 = 'ha';
57840                 }
57841             }
57842
57843             // drop unnecessary precision
57844             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
57845             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
57846
57847             return String(d1.toFixed(p1)) + ' ' + unit1 +
57848                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
57849         }
57850
57851
57852         function redraw() {
57853             if (isHidden) return;
57854
57855             var resolver = context.graph(),
57856                 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
57857                 singular = selected.length === 1 ? selected[0] : null,
57858                 extent$$1 = geoExtent$$1(),
57859                 entity;
57860
57861             wrap.html('');
57862             wrap.append('h4')
57863                 .attr('class', 'infobox-heading fillD')
57864                 .text(singular || t('infobox.selected', { n: selected.length }));
57865
57866             if (!selected.length) return;
57867
57868             var center;
57869             for (var i = 0; i < selected.length; i++) {
57870                 entity = context.entity(selected[i]);
57871                 extent$$1._extend(entity.extent(resolver));
57872             }
57873             center = extent$$1.center();
57874
57875
57876             var list = wrap.append('ul');
57877
57878             // multiple features, just display extent center..
57879             if (!singular) {
57880                 list.append('li')
57881                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
57882                 return;
57883             }
57884
57885             // single feature, display details..
57886             if (!entity) return;
57887             var geometry = entity.geometry(resolver);
57888
57889             if (geometry === 'line' || geometry === 'area') {
57890                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
57891                     feature = entity.asGeoJSON(resolver),
57892                     length = radiansToMeters(d3GeoLength(toLineString(feature))),
57893                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
57894                     centroid = d3GeoCentroid(feature);
57895
57896                 list.append('li')
57897                     .text(t('infobox.geometry') + ': ' +
57898                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
57899
57900                 if (closed) {
57901                     var area$$1 = steradiansToSqmeters(entity.area(resolver));
57902                     list.append('li')
57903                         .text(t('infobox.area') + ': ' + displayArea(area$$1));
57904                 }
57905
57906                 list.append('li')
57907                     .text(lengthLabel + ': ' + displayLength(length));
57908
57909                 list.append('li')
57910                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
57911
57912
57913                 var toggle  = isImperial ? 'imperial' : 'metric';
57914                 wrap.append('a')
57915                     .text(t('infobox.' + toggle))
57916                     .attr('href', '#')
57917                     .attr('class', 'button')
57918                     .on('click', function() {
57919                         event.preventDefault();
57920                         isImperial = !isImperial;
57921                         redraw();
57922                     });
57923
57924             } else {
57925                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
57926
57927                 list.append('li')
57928                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
57929
57930                 list.append('li')
57931                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
57932             }
57933         }
57934
57935
57936         function toggle() {
57937             if (event) {
57938                 event.preventDefault();
57939             }
57940
57941             isHidden = !isHidden;
57942
57943             if (isHidden) {
57944                 wrap
57945                     .style('display', 'block')
57946                     .style('opacity', 1)
57947                     .transition()
57948                     .duration(200)
57949                     .style('opacity', 0)
57950                     .on('end', function() {
57951                         select(this).style('display', 'none');
57952                     });
57953             } else {
57954                 wrap
57955                     .style('display', 'block')
57956                     .style('opacity', 0)
57957                     .transition()
57958                     .duration(200)
57959                     .style('opacity', 1)
57960                     .on('end', function() {
57961                         redraw();
57962                     });
57963             }
57964         }
57965
57966
57967         var wrap = selection$$1.selectAll('.infobox')
57968             .data([0]);
57969
57970         wrap = wrap.enter()
57971             .append('div')
57972             .attr('class', 'infobox fillD2')
57973             .style('display', (isHidden ? 'none' : 'block'))
57974             .merge(wrap);
57975
57976         context.map()
57977             .on('drawn.info', redraw);
57978
57979         redraw();
57980
57981         var keybinding = d3keybinding('info')
57982             .on(key, toggle);
57983
57984         select(document)
57985             .call(keybinding);
57986     }
57987
57988     return info;
57989 }
57990
57991 function uiMapData(context) {
57992     var key = 'F',
57993         features = context.features().keys(),
57994         layers = context.layers(),
57995         fills = ['wireframe', 'partial', 'full'],
57996         fillDefault = context.storage('area-fill') || 'partial',
57997         fillSelected = fillDefault;
57998
57999
58000     function map_data(selection$$1) {
58001
58002         function showsFeature(d) {
58003             return context.features().enabled(d);
58004         }
58005
58006
58007         function autoHiddenFeature(d) {
58008             return context.features().autoHidden(d);
58009         }
58010
58011
58012         function clickFeature(d) {
58013             context.features().toggle(d);
58014             update();
58015         }
58016
58017
58018         function showsFill(d) {
58019             return fillSelected === d;
58020         }
58021
58022
58023         function setFill(d) {
58024             lodash.each(fills, function(opt) {
58025                 context.surface().classed('fill-' + opt, Boolean(opt === d));
58026             });
58027
58028             fillSelected = d;
58029             if (d !== 'wireframe') {
58030                 fillDefault = d;
58031                 context.storage('area-fill', d);
58032             }
58033             update();
58034         }
58035
58036
58037         function showsLayer(which) {
58038             var layer = layers.layer(which);
58039             if (layer) {
58040                 return layer.enabled();
58041             }
58042             return false;
58043         }
58044
58045
58046         function setLayer(which, enabled) {
58047             var layer = layers.layer(which);
58048             if (layer) {
58049                 layer.enabled(enabled);
58050                 update();
58051             }
58052         }
58053
58054
58055         function toggleLayer(which) {
58056             setLayer(which, !showsLayer(which));
58057         }
58058
58059
58060         function clickGpx() {
58061             toggleLayer('gpx');
58062         }
58063
58064
58065         function clickMapillaryImages() {
58066             toggleLayer('mapillary-images');
58067             if (!showsLayer('mapillary-images')) {
58068                 setLayer('mapillary-signs', false);
58069             }
58070         }
58071
58072
58073         function clickMapillarySigns() {
58074             toggleLayer('mapillary-signs');
58075         }
58076
58077
58078         function drawMapillaryItems(selection$$1) {
58079             var mapillaryImages = layers.layer('mapillary-images'),
58080                 mapillarySigns = layers.layer('mapillary-signs'),
58081                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
58082                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
58083                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
58084                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
58085
58086             var mapillaryList = selection$$1
58087                 .selectAll('.layer-list-mapillary')
58088                 .data([0]);
58089
58090             mapillaryList = mapillaryList.enter()
58091                 .append('ul')
58092                 .attr('class', 'layer-list layer-list-mapillary')
58093                 .merge(mapillaryList);
58094
58095
58096             var mapillaryImageLayerItem = mapillaryList
58097                 .selectAll('.list-item-mapillary-images')
58098                 .data(supportsMapillaryImages ? [0] : []);
58099
58100             mapillaryImageLayerItem.exit()
58101                 .remove();
58102
58103             var enterImages = mapillaryImageLayerItem.enter()
58104                 .append('li')
58105                 .attr('class', 'list-item-mapillary-images');
58106
58107             var labelImages = enterImages
58108                 .append('label')
58109                 .call(tooltip()
58110                     .title(t('mapillary_images.tooltip'))
58111                     .placement('top'));
58112
58113             labelImages
58114                 .append('input')
58115                 .attr('type', 'checkbox')
58116                 .on('change', clickMapillaryImages);
58117
58118             labelImages
58119                 .append('span')
58120                 .text(t('mapillary_images.title'));
58121
58122
58123             var mapillarySignLayerItem = mapillaryList
58124                 .selectAll('.list-item-mapillary-signs')
58125                 .data(supportsMapillarySigns ? [0] : []);
58126
58127             mapillarySignLayerItem.exit()
58128                 .remove();
58129
58130             var enterSigns = mapillarySignLayerItem.enter()
58131                 .append('li')
58132                 .attr('class', 'list-item-mapillary-signs');
58133
58134             var labelSigns = enterSigns
58135                 .append('label')
58136                 .call(tooltip()
58137                     .title(t('mapillary_signs.tooltip'))
58138                     .placement('top'));
58139
58140             labelSigns
58141                 .append('input')
58142                 .attr('type', 'checkbox')
58143                 .on('change', clickMapillarySigns);
58144
58145             labelSigns
58146                 .append('span')
58147                 .text(t('mapillary_signs.title'));
58148
58149
58150             // Updates
58151             mapillaryImageLayerItem = mapillaryImageLayerItem
58152                 .merge(enterImages);
58153
58154             mapillaryImageLayerItem
58155                 .classed('active', showsMapillaryImages)
58156                 .selectAll('input')
58157                 .property('checked', showsMapillaryImages);
58158
58159
58160             mapillarySignLayerItem = mapillarySignLayerItem
58161                 .merge(enterSigns);
58162
58163             mapillarySignLayerItem
58164                 .classed('active', showsMapillarySigns)
58165                 .selectAll('input')
58166                 .property('disabled', !showsMapillaryImages)
58167                 .property('checked', showsMapillarySigns);
58168
58169             mapillarySignLayerItem
58170                 .selectAll('label')
58171                 .classed('deemphasize', !showsMapillaryImages);
58172         }
58173
58174
58175         function drawGpxItem(selection$$1) {
58176             var gpx = layers.layer('gpx'),
58177                 hasGpx = gpx && gpx.hasGpx(),
58178                 showsGpx = hasGpx && gpx.enabled();
58179
58180             var gpxLayerItem = selection$$1
58181                 .selectAll('.layer-list-gpx')
58182                 .data(gpx ? [0] : []);
58183
58184             // Exit
58185             gpxLayerItem.exit()
58186                 .remove();
58187
58188             // Enter
58189             var enter = gpxLayerItem.enter()
58190                 .append('ul')
58191                 .attr('class', 'layer-list layer-list-gpx')
58192                 .append('li')
58193                 .classed('list-item-gpx', true);
58194
58195             enter
58196                 .append('button')
58197                 .attr('class', 'list-item-gpx-extent')
58198                 .call(tooltip()
58199                     .title(t('gpx.zoom'))
58200                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
58201                 .on('click', function() {
58202                     event.preventDefault();
58203                     event.stopPropagation();
58204                     gpx.fitZoom();
58205                 })
58206                 .call(svgIcon('#icon-search'));
58207
58208             enter
58209                 .append('button')
58210                 .attr('class', 'list-item-gpx-browse')
58211                 .call(tooltip()
58212                     .title(t('gpx.browse'))
58213                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
58214                 .on('click', function() {
58215                     select(document.createElement('input'))
58216                         .attr('type', 'file')
58217                         .on('change', function() {
58218                             gpx.files(event.target.files);
58219                         })
58220                         .node().click();
58221                 })
58222                 .call(svgIcon('#icon-geolocate'));
58223
58224             var labelGpx = enter
58225                 .append('label')
58226                 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
58227
58228             labelGpx
58229                 .append('input')
58230                 .attr('type', 'checkbox')
58231                 .on('change', clickGpx);
58232
58233             labelGpx
58234                 .append('span')
58235                 .text(t('gpx.local_layer'));
58236
58237
58238             // Update
58239             gpxLayerItem = gpxLayerItem
58240                 .merge(enter);
58241
58242             gpxLayerItem
58243                 .classed('active', showsGpx)
58244                 .selectAll('input')
58245                 .property('disabled', !hasGpx)
58246                 .property('checked', showsGpx);
58247
58248             gpxLayerItem
58249                 .selectAll('label')
58250                 .classed('deemphasize', !hasGpx);
58251         }
58252
58253
58254         function drawList(selection$$1, data, type, name, change, active$$1) {
58255             var items = selection$$1.selectAll('li')
58256                 .data(data);
58257
58258             // Exit
58259             items.exit()
58260                 .remove();
58261
58262             // Enter
58263             var enter = items.enter()
58264                 .append('li')
58265                 .attr('class', 'layer')
58266                 .call(tooltip()
58267                     .html(true)
58268                     .title(function(d) {
58269                         var tip = t(name + '.' + d + '.tooltip'),
58270                             key = (d === 'wireframe' ? 'W' : null);
58271
58272                         if (name === 'feature' && autoHiddenFeature(d)) {
58273                             tip += '<div>' + t('map_data.autohidden') + '</div>';
58274                         }
58275                         return uiTooltipHtml(tip, key);
58276                     })
58277                     .placement('top')
58278                 );
58279
58280             var label = enter
58281                 .append('label');
58282
58283             label
58284                 .append('input')
58285                 .attr('type', type)
58286                 .attr('name', name)
58287                 .on('change', change);
58288
58289             label
58290                 .append('span')
58291                 .text(function(d) { return t(name + '.' + d + '.description'); });
58292
58293             // Update
58294             items = items
58295                 .merge(enter);
58296
58297             items
58298                 .classed('active', active$$1)
58299                 .selectAll('input')
58300                 .property('checked', active$$1)
58301                 .property('indeterminate', function(d) {
58302                     return (name === 'feature' && autoHiddenFeature(d));
58303                 });
58304         }
58305
58306
58307         function update() {
58308             dataLayerContainer.call(drawMapillaryItems);
58309             dataLayerContainer.call(drawGpxItem);
58310
58311             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
58312             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
58313         }
58314
58315
58316         function hidePanel() {
58317             setVisible(false);
58318         }
58319
58320
58321         function togglePanel() {
58322             if (event) event.preventDefault();
58323             tooltipBehavior.hide(button);
58324             setVisible(!button.classed('active'));
58325         }
58326
58327
58328         function toggleWireframe() {
58329             if (event) {
58330                 event.preventDefault();
58331                 event.stopPropagation();
58332             }
58333             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
58334             context.map().pan([0,0]);  // trigger a redraw
58335         }
58336
58337
58338         function setVisible(show) {
58339             if (show !== shown) {
58340                 button.classed('active', show);
58341                 shown = show;
58342
58343                 if (show) {
58344                     update();
58345                     selection$$1.on('mousedown.map_data-inside', function() {
58346                         return event.stopPropagation();
58347                     });
58348                     content.style('display', 'block')
58349                         .style('right', '-300px')
58350                         .transition()
58351                         .duration(200)
58352                         .style('right', '0px');
58353                 } else {
58354                     content.style('display', 'block')
58355                         .style('right', '0px')
58356                         .transition()
58357                         .duration(200)
58358                         .style('right', '-300px')
58359                         .on('end', function() {
58360                             select(this).style('display', 'none');
58361                         });
58362                     selection$$1.on('mousedown.map_data-inside', null);
58363                 }
58364             }
58365         }
58366
58367
58368         var content = selection$$1
58369                 .append('div')
58370                 .attr('class', 'fillL map-overlay col3 content hide'),
58371             tooltipBehavior = tooltip()
58372                 .placement((textDirection === 'rtl') ? 'right' : 'left')
58373                 .html(true)
58374                 .title(uiTooltipHtml(t('map_data.description'), key)),
58375             button = selection$$1
58376                 .append('button')
58377                 .attr('tabindex', -1)
58378                 .on('click', togglePanel)
58379                 .call(svgIcon('#icon-data', 'light'))
58380                 .call(tooltipBehavior),
58381             shown = false;
58382
58383         content
58384             .append('h4')
58385             .text(t('map_data.title'));
58386
58387
58388         // data layers
58389         content
58390             .append('a')
58391             .text(t('map_data.data_layers'))
58392             .attr('href', '#')
58393             .classed('hide-toggle', true)
58394             .classed('expanded', true)
58395             .on('click', function() {
58396                 var exp = select(this).classed('expanded');
58397                 dataLayerContainer.style('display', exp ? 'none' : 'block');
58398                 select(this).classed('expanded', !exp);
58399                 event.preventDefault();
58400             });
58401
58402         var dataLayerContainer = content
58403             .append('div')
58404             .attr('class', 'data-data-layers')
58405             .style('display', 'block');
58406
58407
58408         // area fills
58409         content
58410             .append('a')
58411             .text(t('map_data.fill_area'))
58412             .attr('href', '#')
58413             .classed('hide-toggle', true)
58414             .classed('expanded', false)
58415             .on('click', function() {
58416                 var exp = select(this).classed('expanded');
58417                 fillContainer.style('display', exp ? 'none' : 'block');
58418                 select(this).classed('expanded', !exp);
58419                 event.preventDefault();
58420             });
58421
58422         var fillContainer = content
58423             .append('div')
58424             .attr('class', 'data-area-fills')
58425             .style('display', 'none');
58426
58427         var fillList = fillContainer
58428             .append('ul')
58429             .attr('class', 'layer-list layer-fill-list');
58430
58431
58432         // feature filters
58433         content
58434             .append('a')
58435             .text(t('map_data.map_features'))
58436             .attr('href', '#')
58437             .classed('hide-toggle', true)
58438             .classed('expanded', false)
58439             .on('click', function() {
58440                 var exp = select(this).classed('expanded');
58441                 featureContainer.style('display', exp ? 'none' : 'block');
58442                 select(this).classed('expanded', !exp);
58443                 event.preventDefault();
58444             });
58445
58446         var featureContainer = content
58447             .append('div')
58448             .attr('class', 'data-feature-filters')
58449             .style('display', 'none');
58450
58451         var featureList = featureContainer
58452             .append('ul')
58453             .attr('class', 'layer-list layer-feature-list');
58454
58455
58456         context.features()
58457             .on('change.map_data-update', update);
58458
58459         setFill(fillDefault);
58460
58461         var keybinding = d3keybinding('features')
58462             .on(key, togglePanel)
58463             .on('W', toggleWireframe)
58464             .on('B', hidePanel)
58465             .on('H', hidePanel);
58466
58467         select(document)
58468             .call(keybinding);
58469
58470         context.surface().on('mousedown.map_data-outside', hidePanel);
58471         context.container().on('mousedown.map_data-outside', hidePanel);
58472     }
58473
58474
58475     return map_data;
58476 }
58477
58478 function uiModes(context) {
58479     var modes = [
58480         modeAddPoint$$1(context),
58481         modeAddLine$$1(context),
58482         modeAddArea$$1(context)
58483     ];
58484
58485
58486     function editable() {
58487         return context.editable() && context.mode().id !== 'save';
58488     }
58489
58490
58491     return function(selection$$1) {
58492         var buttons = selection$$1.selectAll('button.add-button')
58493             .data(modes);
58494
58495         buttons = buttons.enter()
58496             .append('button')
58497             .attr('tabindex', -1)
58498             .attr('class', function(mode) { return mode.id + ' add-button col4'; })
58499             .on('click.mode-buttons', function(mode) {
58500                 if (mode.id === context.mode().id) {
58501                     context.enter(modeBrowse$$1(context));
58502                 } else {
58503                     context.enter(mode);
58504                 }
58505             })
58506             .call(tooltip()
58507                 .placement('bottom')
58508                 .html(true)
58509                 .title(function(mode) {
58510                     return uiTooltipHtml(mode.description, mode.key);
58511                 })
58512             );
58513
58514         context.map()
58515             .on('move.modes', lodash.debounce(update, 500));
58516
58517         context
58518             .on('enter.modes', update);
58519
58520         buttons
58521             .each(function(d) {
58522                 select(this)
58523                     .call(svgIcon('#icon-' + d.button, 'pre-text'));
58524             });
58525
58526         buttons
58527             .append('span')
58528             .attr('class', 'label')
58529             .text(function(mode) { return mode.title; });
58530
58531         context
58532             .on('enter.editor', function(entered) {
58533                 selection$$1.selectAll('button.add-button')
58534                     .classed('active', function(mode) { return entered.button === mode.button; });
58535                 context.container()
58536                     .classed('mode-' + entered.id, true);
58537             });
58538
58539         context
58540             .on('exit.editor', function(exited) {
58541                 context.container()
58542                     .classed('mode-' + exited.id, false);
58543             });
58544
58545         var keybinding = d3keybinding('mode-buttons');
58546
58547         modes.forEach(function(m) {
58548             keybinding.on(m.key, function() {
58549                 if (editable()) context.enter(m);
58550             });
58551         });
58552
58553         select(document)
58554             .call(keybinding);
58555
58556
58557         function update() {
58558             selection$$1.selectAll('button.add-button')
58559                 .property('disabled', !editable());
58560         }
58561     };
58562 }
58563
58564 function uiRestore(context) {
58565
58566     return function(selection) {
58567         if (!context.history().lock() || !context.history().restorableChanges())
58568             return;
58569
58570         var modalSelection = uiModal(selection, true);
58571
58572         modalSelection.select('.modal')
58573             .attr('class', 'modal fillL col6');
58574
58575         var introModal = modalSelection.select('.content');
58576
58577         introModal
58578             .attr('class','cf');
58579
58580         introModal
58581             .append('div')
58582             .attr('class', 'modal-section')
58583             .append('h3')
58584             .text(t('restore.heading'));
58585
58586         introModal
58587             .append('div')
58588             .attr('class','modal-section')
58589             .append('p')
58590             .text(t('restore.description'));
58591
58592         var buttonWrap = introModal
58593             .append('div')
58594             .attr('class', 'modal-actions cf');
58595
58596         var restore = buttonWrap
58597             .append('button')
58598             .attr('class', 'restore col6')
58599             .text(t('restore.restore'))
58600             .on('click', function() {
58601                 context.history().restore();
58602                 modalSelection.remove();
58603             });
58604
58605         buttonWrap
58606             .append('button')
58607             .attr('class', 'reset col6')
58608             .text(t('restore.reset'))
58609             .on('click', function() {
58610                 context.history().clearSaved();
58611                 modalSelection.remove();
58612             });
58613
58614         restore.node().focus();
58615     };
58616 }
58617
58618 function uiSave(context) {
58619     var history = context.history(),
58620         key = uiCmd('⌘S');
58621
58622
58623     function saving() {
58624         return context.mode().id === 'save';
58625     }
58626
58627
58628     function save() {
58629         event.preventDefault();
58630         if (!context.inIntro() && !saving() && history.hasChanges()) {
58631             context.enter(modeSave$$1(context));
58632         }
58633     }
58634
58635
58636     function getBackground(numChanges) {
58637         var step;
58638         if (numChanges === 0) {
58639             return null;
58640         } else if (numChanges <= 50) {
58641             step = numChanges / 50;
58642             return interpolateRgb('#fff', '#ff8')(step);  // white -> yellow
58643         } else {
58644             step = Math.min((numChanges - 50) / 50, 1.0);
58645             return interpolateRgb('#ff8', '#f88')(step);  // yellow -> red
58646         }
58647     }
58648
58649
58650     return function(selection$$1) {
58651         var tooltipBehavior = tooltip()
58652             .placement('bottom')
58653             .html(true)
58654             .title(uiTooltipHtml(t('save.no_changes'), key));
58655
58656         var button = selection$$1
58657             .append('button')
58658             .attr('class', 'save col12 disabled')
58659             .attr('tabindex', -1)
58660             .on('click', save)
58661             .call(tooltipBehavior);
58662
58663         button
58664             .append('span')
58665             .attr('class', 'label')
58666             .text(t('save.title'));
58667
58668         button
58669             .append('span')
58670             .attr('class', 'count')
58671             .text('0');
58672
58673         var keybinding = d3keybinding('undo-redo')
58674             .on(key, save, true);
58675
58676         select(document)
58677             .call(keybinding);
58678
58679         var numChanges = 0;
58680
58681         context.history()
58682             .on('change.save', function() {
58683                 var _ = history.difference().summary().length;
58684                 if (_ === numChanges)
58685                     return;
58686                 numChanges = _;
58687
58688                 tooltipBehavior.title(uiTooltipHtml(
58689                     t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key));
58690
58691                 var background = getBackground(numChanges);
58692
58693                 button
58694                     .classed('disabled', numChanges === 0)
58695                     .classed('has-count', numChanges > 0)
58696                     .style('background', background);
58697
58698                 button.select('span.count')
58699                     .text(numChanges)
58700                     .style('background', background)
58701                     .style('border-color', background);
58702             });
58703
58704         context
58705             .on('enter.save', function() {
58706                 button.property('disabled', saving());
58707                 if (saving()) button.call(tooltipBehavior.hide);
58708             });
58709     };
58710 }
58711
58712 function uiScale(context) {
58713     var projection = context.projection,
58714         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
58715         maxLength = 180,
58716         tickHeight = 8;
58717
58718
58719     function scaleDefs(loc1, loc2) {
58720         var lat = (loc2[1] + loc1[1]) / 2,
58721             conversion = (isImperial ? 3.28084 : 1),
58722             dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
58723             scale = { dist: 0, px: 0, text: '' },
58724             buckets, i, val, dLon;
58725
58726         if (isImperial) {
58727             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
58728         } else {
58729             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
58730         }
58731
58732         // determine a user-friendly endpoint for the scale
58733         for (i = 0; i < buckets.length; i++) {
58734             val = buckets[i];
58735             if (dist >= val) {
58736                 scale.dist = Math.floor(dist / val) * val;
58737                 break;
58738             } else {
58739                 scale.dist = +dist.toFixed(2);
58740             }
58741         }
58742
58743         dLon = geoMetersToLon(scale.dist / conversion, lat);
58744         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
58745
58746         if (isImperial) {
58747             if (scale.dist >= 5280) {
58748                 scale.dist /= 5280;
58749                 scale.text = String(scale.dist) + ' mi';
58750             } else {
58751                 scale.text = String(scale.dist) + ' ft';
58752             }
58753         } else {
58754             if (scale.dist >= 1000) {
58755                 scale.dist /= 1000;
58756                 scale.text = String(scale.dist) + ' km';
58757             } else {
58758                 scale.text = String(scale.dist) + ' m';
58759             }
58760         }
58761
58762         return scale;
58763     }
58764
58765
58766     function update(selection) {
58767         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
58768         var dims = context.map().dimensions(),
58769             loc1 = projection.invert([0, dims[1]]),
58770             loc2 = projection.invert([maxLength, dims[1]]),
58771             scale = scaleDefs(loc1, loc2);
58772
58773         selection.select('#scalepath')
58774             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
58775
58776         selection.select('#scaletext')
58777             .attr('x', scale.px + 8)
58778             .attr('y', tickHeight)
58779             .text(scale.text);
58780     }
58781
58782
58783     return function(selection) {
58784         function switchUnits() {
58785             isImperial = !isImperial;
58786             selection.call(update);
58787         }
58788
58789         var g = selection.append('svg')
58790             .attr('id', 'scale')
58791             .on('click', switchUnits)
58792             .append('g')
58793             .attr('transform', 'translate(10,11)');
58794
58795         g.append('path').attr('id', 'scalepath');
58796         g.append('text').attr('id', 'scaletext');
58797
58798         selection.call(update);
58799
58800         context.map().on('move.scale', function() {
58801             update(selection);
58802         });
58803     };
58804 }
58805
58806 var pair_1 = pair;
58807 function search(x, dims, r) {
58808   if (!dims) dims = 'NSEW';
58809   if (typeof x !== 'string') return { val: null, regex: r };
58810   r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
58811   var m = r.exec(x);
58812   if (!m) return { val: null, regex: r };
58813   else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
58814   else return {
58815     val: (((m[1]) ? parseFloat(m[1]) : 0) +
58816           ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
58817           ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
58818           ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
58819     regex: r,
58820     raw: m[0],
58821     dim: m[4]
58822   };
58823 }
58824
58825 function pair(x, dims) {
58826   x = x.trim();
58827   var one = search(x, dims);
58828   if (one.val === null) return null;
58829   var two = search(x, dims, one.regex);
58830   if (two.val === null) return null;
58831   // null if one/two are not contiguous.
58832   if (one.raw + two.raw !== x) return null;
58833   if (one.dim) {
58834     return swapdim(one.val, two.val, one.dim);
58835   } else {
58836     return [one.val, two.val];
58837   }
58838 }
58839
58840 function swapdim(a, b, dim) {
58841   if (dim === 'N' || dim === 'S') return [a, b];
58842   if (dim === 'W' || dim === 'E') return [b, a];
58843 }
58844
58845 function uiFeatureList(context) {
58846     var geocodeResults;
58847
58848
58849     function featureList(selection$$1) {
58850         var header = selection$$1.append('div')
58851             .attr('class', 'header fillL cf');
58852
58853         header.append('h3')
58854             .text(t('inspector.feature_list'));
58855
58856         var searchWrap = selection$$1.append('div')
58857             .attr('class', 'search-header');
58858
58859         var search = searchWrap.append('input')
58860             .attr('placeholder', t('inspector.search'))
58861             .attr('type', 'search')
58862             .on('keypress', keypress)
58863             .on('input', inputevent);
58864
58865         searchWrap
58866             .call(svgIcon('#icon-search', 'pre-text'));
58867
58868         var listWrap = selection$$1.append('div')
58869             .attr('class', 'inspector-body');
58870
58871         var list = listWrap.append('div')
58872             .attr('class', 'feature-list cf');
58873
58874         context
58875             .on('exit.feature-list', clearSearch);
58876         context.map()
58877             .on('drawn.feature-list', mapDrawn);
58878
58879
58880         function keypress() {
58881             var q = search.property('value'),
58882                 items = list.selectAll('.feature-list-item');
58883             if (event.keyCode === 13 && q.length && items.size()) {
58884                 click(items.datum());
58885             }
58886         }
58887
58888
58889         function inputevent() {
58890             geocodeResults = undefined;
58891             drawList();
58892         }
58893
58894
58895         function clearSearch() {
58896             search.property('value', '');
58897             drawList();
58898         }
58899
58900
58901         function mapDrawn(e) {
58902             if (e.full) {
58903                 drawList();
58904             }
58905         }
58906
58907
58908         function features() {
58909             var entities = {},
58910                 result = [],
58911                 graph = context.graph(),
58912                 q = search.property('value').toLowerCase();
58913
58914             if (!q) return result;
58915
58916             var idMatch = q.match(/^([nwr])([0-9]+)$/);
58917
58918             if (idMatch) {
58919                 result.push({
58920                     id: idMatch[0],
58921                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
58922                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
58923                     name: idMatch[2]
58924                 });
58925             }
58926
58927             var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
58928
58929             if (locationMatch) {
58930                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
58931                 result.push({
58932                     id: -1,
58933                     geometry: 'point',
58934                     type: t('inspector.location'),
58935                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
58936                     location: loc
58937                 });
58938             }
58939
58940             function addEntity(entity) {
58941                 if (entity.id in entities || result.length > 200)
58942                     return;
58943
58944                 entities[entity.id] = true;
58945
58946                 var name = utilDisplayName(entity) || '';
58947                 if (name.toLowerCase().indexOf(q) >= 0) {
58948                     var matched = context.presets().match(entity, graph),
58949                         type = (matched && matched.name()) || utilDisplayType(entity.id);
58950                     result.push({
58951                         id: entity.id,
58952                         entity: entity,
58953                         geometry: context.geometry(entity.id),
58954                         type: type,
58955                         name: name
58956                     });
58957                 }
58958
58959                 graph.parentRelations(entity).forEach(function(parent) {
58960                     addEntity(parent);
58961                 });
58962             }
58963
58964             var visible = context.surface().selectAll('.point, .line, .area').nodes();
58965             for (var i = 0; i < visible.length && result.length <= 200; i++) {
58966                 addEntity(visible[i].__data__);
58967             }
58968
58969             (geocodeResults || []).forEach(function(d) {
58970                 // https://github.com/openstreetmap/iD/issues/1890
58971                 if (d.osm_type && d.osm_id) {
58972                     result.push({
58973                         id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
58974                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
58975                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
58976                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
58977                         name: d.display_name,
58978                         extent: new geoExtent$$1(
58979                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
58980                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
58981                     });
58982                 }
58983             });
58984
58985             return result;
58986         }
58987
58988
58989         function drawList() {
58990             var value = search.property('value'),
58991                 results = features();
58992
58993             list.classed('filtered', value.length);
58994
58995             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
58996
58997             var resultsIndicator = list.selectAll('.no-results-item')
58998                 .data([0])
58999                 .enter().append('button')
59000                 .property('disabled', true)
59001                 .attr('class', 'no-results-item')
59002                 .call(svgIcon('#icon-alert', 'pre-text'));
59003
59004             resultsIndicator.append('span')
59005                 .attr('class', 'entity-name');
59006
59007             list.selectAll('.no-results-item .entity-name')
59008                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
59009
59010             list.selectAll('.geocode-item')
59011                 .data([0])
59012                 .enter().append('button')
59013                 .attr('class', 'geocode-item')
59014                 .on('click', geocode)
59015                 .append('div')
59016                 .attr('class', 'label')
59017                 .append('span')
59018                 .attr('class', 'entity-name')
59019                 .text(t('geocoder.search'));
59020
59021             list.selectAll('.no-results-item')
59022                 .style('display', (value.length && !results.length) ? 'block' : 'none');
59023
59024             list.selectAll('.geocode-item')
59025                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
59026
59027             list.selectAll('.feature-list-item')
59028                 .data([-1])
59029                 .remove();
59030
59031             var items = list.selectAll('.feature-list-item')
59032                 .data(results, function(d) { return d.id; });
59033
59034             var enter = items.enter()
59035                 .insert('button', '.geocode-item')
59036                 .attr('class', 'feature-list-item')
59037                 .on('mouseover', mouseover)
59038                 .on('mouseout', mouseout)
59039                 .on('click', click);
59040
59041             var label = enter
59042                 .append('div')
59043                 .attr('class', 'label');
59044
59045             label.each(function(d) {
59046                 select(this)
59047                     .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
59048             });
59049
59050             label.append('span')
59051                 .attr('class', 'entity-type')
59052                 .text(function(d) { return d.type; });
59053
59054             label.append('span')
59055                 .attr('class', 'entity-name')
59056                 .text(function(d) { return d.name; });
59057
59058             enter.style('opacity', 0)
59059                 .transition()
59060                 .style('opacity', 1);
59061
59062             items.order();
59063
59064             items.exit()
59065                 .remove();
59066         }
59067
59068
59069         function mouseover(d) {
59070             if (d.id === -1) return;
59071
59072             context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
59073                 .classed('hover', true);
59074         }
59075
59076
59077         function mouseout() {
59078             context.surface().selectAll('.hover')
59079                 .classed('hover', false);
59080         }
59081
59082
59083         function click(d) {
59084             event.preventDefault();
59085             if (d.location) {
59086                 context.map().centerZoom([d.location[1], d.location[0]], 20);
59087             }
59088             else if (d.entity) {
59089                 if (d.entity.type === 'node') {
59090                     context.map().center(d.entity.loc);
59091                 } else if (d.entity.type === 'way') {
59092                     var center = context.projection(context.map().center()),
59093                         edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
59094                     context.map().center(edge.loc);
59095                 }
59096                 context.enter(modeSelect(context, [d.entity.id]).suppressMenu(true));
59097             } else {
59098                 context.zoomToEntity(d.id);
59099             }
59100         }
59101
59102
59103         function geocode() {
59104             var searchVal = encodeURIComponent(search.property('value'));
59105             json('https://nominatim.openstreetmap.org/search/' + searchVal + '?limit=10&format=json', function(err, resp) {
59106                 geocodeResults = resp || [];
59107                 drawList();
59108             });
59109         }
59110     }
59111
59112
59113     return featureList;
59114 }
59115
59116 function uiPresetIcon() {
59117     var preset, geometry;
59118
59119
59120     function presetIcon(selection$$1) {
59121         selection$$1.each(render);
59122     }
59123
59124
59125     function render() {
59126         var selection$$1 = select(this),
59127             p = preset.apply(this, arguments),
59128             geom = geometry.apply(this, arguments),
59129             picon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
59130             isMaki = dataFeatureIcons.hasOwnProperty(picon + '-24');
59131
59132         if (picon === 'dentist') {
59133             isMaki = true;  // workaround for dentist icon missing in `maki-sprite.json`
59134         }
59135
59136         function tag_classes(p) {
59137             var s = '';
59138             for (var i in p.tags) {
59139                 s += ' tag-' + i;
59140                 if (p.tags[i] !== '*') {
59141                     s += ' tag-' + i + '-' + p.tags[i];
59142                 }
59143             }
59144             return s;
59145         }
59146
59147         var fill = selection$$1.selectAll('.preset-icon-fill')
59148             .data([0]);
59149
59150         fill = fill.enter()
59151             .append('div')
59152             .merge(fill);
59153
59154         fill
59155             .attr('class', function() {
59156                 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
59157             });
59158
59159         var frame = selection$$1.selectAll('.preset-icon-frame')
59160             .data([0]);
59161
59162         frame = frame.enter()
59163             .append('div')
59164             .call(svgIcon('#preset-icon-frame'))
59165             .merge(frame);
59166
59167         frame
59168             .attr('class', function() {
59169                 return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
59170             });
59171
59172
59173         var icon = selection$$1.selectAll('.preset-icon')
59174             .data([0]);
59175
59176         icon = icon.enter()
59177             .append('div')
59178             .attr('class', 'preset-icon')
59179             .call(svgIcon(''))
59180             .merge(icon);
59181
59182         icon
59183             .attr('class', 'preset-icon preset-icon-' + (isMaki ? '32' : (geom === 'area' ? '44' : '60')));
59184
59185         icon.selectAll('svg')
59186             .attr('class', function() {
59187                 return 'icon ' + picon + tag_classes(p);
59188             });
59189
59190         icon.selectAll('use')       // workaround: maki parking-24 broken?
59191             .attr('href', '#' + picon + (isMaki ? (picon === 'parking' ? '-18' : '-24') : ''));
59192     }
59193
59194
59195     presetIcon.preset = function(_) {
59196         if (!arguments.length) return preset;
59197         preset = utilFunctor(_);
59198         return presetIcon;
59199     };
59200
59201
59202     presetIcon.geometry = function(_) {
59203         if (!arguments.length) return geometry;
59204         geometry = utilFunctor(_);
59205         return presetIcon;
59206     };
59207
59208     return presetIcon;
59209 }
59210
59211 function d3combobox() {
59212     var event$$1 = dispatch('accept'),
59213         data = [],
59214         suggestions = [],
59215         minItems = 2,
59216         caseSensitive = false;
59217
59218     var fetcher = function(val, cb) {
59219         cb(data.filter(function(d) {
59220             return d.value
59221                 .toString()
59222                 .toLowerCase()
59223                 .indexOf(val.toLowerCase()) !== -1;
59224         }));
59225     };
59226
59227     var combobox = function(input, attachTo) {
59228         var idx = -1,
59229             container = select(document.body)
59230                 .selectAll('div.combobox')
59231                 .filter(function(d) { return d === input.node(); }),
59232             shown = !container.empty();
59233
59234         input
59235             .classed('combobox-input', true)
59236             .on('focus.typeahead', focus)
59237             .on('blur.typeahead', blur)
59238             .on('keydown.typeahead', keydown)
59239             .on('keyup.typeahead', keyup)
59240             .on('input.typeahead', change)
59241             .each(function() {
59242                 var parent = this.parentNode,
59243                     sibling = this.nextSibling;
59244
59245                 var caret = select(parent).selectAll('.combobox-caret')
59246                     .filter(function(d) { return d === input.node(); })
59247                     .data([input.node()]);
59248
59249                 caret = caret.enter()
59250                   .insert('div', function() { return sibling; })
59251                     .attr('class', 'combobox-caret')
59252                   .merge(caret);
59253
59254                 caret
59255                     .on('mousedown', function () {
59256                         // prevent the form element from blurring. it blurs
59257                         // on mousedown
59258                         event.stopPropagation();
59259                         event.preventDefault();
59260                         if (!shown) {
59261                             input.node().focus();
59262                             fetch('', render);
59263                         } else {
59264                             hide();
59265                         }
59266                     });
59267             });
59268
59269         function focus() {
59270             fetch(value(), render);
59271         }
59272
59273         function blur() {
59274             window.setTimeout(hide, 150);
59275         }
59276
59277         function show() {
59278             if (!shown) {
59279                 container = select(document.body)
59280                     .insert('div', ':first-child')
59281                     .datum(input.node())
59282                     .attr('class', 'combobox')
59283                     .style('position', 'absolute')
59284                     .style('display', 'block')
59285                     .style('left', '0px')
59286                     .on('mousedown', function () {
59287                         // prevent moving focus out of the text field
59288                         event.preventDefault();
59289                     });
59290
59291                 select(document.body)
59292                     .on('scroll.combobox', render, true);
59293
59294                 shown = true;
59295             }
59296         }
59297
59298         function hide() {
59299             if (shown) {
59300                 idx = -1;
59301                 container.remove();
59302
59303                 select(document.body)
59304                     .on('scroll.combobox', null);
59305
59306                 shown = false;
59307             }
59308         }
59309
59310         function keydown() {
59311            switch (event.keyCode) {
59312                // backspace, delete
59313                case 8:
59314                case 46:
59315                    input.on('input.typeahead', function() {
59316                        idx = -1;
59317                        render();
59318                        var start = input.property('selectionStart');
59319                        input.node().setSelectionRange(start, start);
59320                        input.on('input.typeahead', change);
59321                    });
59322                    break;
59323                // tab
59324                case 9:
59325                    container.selectAll('a.selected').each(function (d) {
59326                        event$$1.call('accept', this, d);
59327                    });
59328                    hide();
59329                    break;
59330                // return
59331                case 13:
59332                    event.preventDefault();
59333                    break;
59334                // up arrow
59335                case 38:
59336                    nav(-1);
59337                    event.preventDefault();
59338                    break;
59339                // down arrow
59340                case 40:
59341                    nav(+1);
59342                    event.preventDefault();
59343                    break;
59344            }
59345            event.stopPropagation();
59346         }
59347
59348         function keyup() {
59349             switch (event.keyCode) {
59350                 // escape
59351                 case 27:
59352                     hide();
59353                     break;
59354                 // return
59355                 case 13:
59356                     container.selectAll('a.selected').each(function (d) {
59357                        event$$1.call('accept', this, d);
59358                     });
59359                     hide();
59360                     break;
59361             }
59362         }
59363
59364         function change() {
59365             fetch(value(), function() {
59366                 if (input.property('selectionEnd') === input.property('value').length) {
59367                     autocomplete();
59368                 }
59369                 render();
59370             });
59371         }
59372
59373         function nav(dir) {
59374             if (!suggestions.length) return;
59375             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
59376             input.property('value', suggestions[idx].value);
59377             render();
59378             ensureVisible();
59379         }
59380
59381         function value() {
59382             var value = input.property('value'),
59383                 start = input.property('selectionStart'),
59384                 end = input.property('selectionEnd');
59385
59386             if (start && end) {
59387                 value = value.substring(0, start);
59388             }
59389
59390             return value;
59391         }
59392
59393         function fetch(v, cb) {
59394             fetcher.call(input, v, function(_) {
59395                 suggestions = _;
59396                 cb();
59397             });
59398         }
59399
59400         function autocomplete() {
59401             var v = caseSensitive ? value() : value().toLowerCase();
59402             idx = -1;
59403             if (!v) return;
59404
59405             for (var i = 0; i < suggestions.length; i++) {
59406                 var suggestion = suggestions[i].value,
59407                     compare = caseSensitive ? suggestion : suggestion.toLowerCase();
59408
59409                 if (compare.indexOf(v) === 0) {
59410                     idx = i;
59411                     input.property('value', suggestion);
59412                     input.node().setSelectionRange(v.length, suggestion.length);
59413                     return;
59414                 }
59415             }
59416         }
59417
59418         function render() {
59419             if (suggestions.length >= minItems && document.activeElement === input.node()) {
59420                 show();
59421             } else {
59422                 hide();
59423                 return;
59424             }
59425
59426             var options = container
59427                 .selectAll('a.combobox-option')
59428                 .data(suggestions, function(d) { return d.value; });
59429
59430             options.exit()
59431                 .remove();
59432
59433             options.enter()
59434                 .append('a')
59435                 .attr('class', 'combobox-option')
59436                 .text(function(d) { return d.value; })
59437                 .merge(options)
59438                 .attr('title', function(d) { return d.title; })
59439                 .classed('selected', function(d, i) { return i === idx; })
59440                 .on('mouseover', select$$1)
59441                 .on('click', accept)
59442                 .order();
59443
59444
59445             var node = attachTo ? attachTo.node() : input.node(),
59446                 rect = node.getBoundingClientRect();
59447
59448             container
59449                 .style('left', rect.left + 'px')
59450                 .style('width', rect.width + 'px')
59451                 .style('top', rect.height + rect.top + 'px');
59452         }
59453
59454         function select$$1(d, i) {
59455             idx = i;
59456             render();
59457         }
59458
59459         function ensureVisible() {
59460             var node = container.selectAll('a.selected').node();
59461             if (node) node.scrollIntoView();
59462         }
59463
59464         function accept(d) {
59465             if (!shown) return;
59466             input
59467                 .property('value', d.value)
59468                 .dispatch('change');
59469             event$$1.call('accept', this, d);
59470             hide();
59471         }
59472     };
59473
59474     combobox.fetcher = function(_) {
59475         if (!arguments.length) return fetcher;
59476         fetcher = _;
59477         return combobox;
59478     };
59479
59480     combobox.data = function(_) {
59481         if (!arguments.length) return data;
59482         data = _;
59483         return combobox;
59484     };
59485
59486     combobox.minItems = function(_) {
59487         if (!arguments.length) return minItems;
59488         minItems = _;
59489         return combobox;
59490     };
59491
59492     combobox.caseSensitive = function(_) {
59493         if (!arguments.length) return caseSensitive;
59494         caseSensitive = _;
59495         return combobox;
59496     };
59497
59498     return utilRebind(combobox, event$$1, 'on');
59499 }
59500
59501
59502 d3combobox.off = function(input) {
59503     input
59504         .on('focus.typeahead', null)
59505         .on('blur.typeahead', null)
59506         .on('keydown.typeahead', null)
59507         .on('keyup.typeahead', null)
59508         .on('input.typeahead', null)
59509         .each(function() {
59510             select(this.parentNode).selectAll('.combobox-caret')
59511                 .filter(function(d) { return d === input.node(); })
59512                 .on('mousedown', null);
59513         });
59514
59515     select(document.body)
59516         .on('scroll.combobox', null);
59517 };
59518
59519 function uiDisclosure() {
59520     var dispatch$$1 = dispatch('toggled'),
59521         title,
59522         expanded = false,
59523         content = function () {};
59524
59525
59526     var disclosure = function(selection$$1) {
59527         var hideToggle = selection$$1.selectAll('.hide-toggle')
59528             .data([0]);
59529
59530         hideToggle = hideToggle.enter()
59531             .append('a')
59532             .attr('href', '#')
59533             .attr('class', 'hide-toggle')
59534             .merge(hideToggle);
59535
59536         hideToggle
59537             .text(title)
59538             .on('click', toggle)
59539             .classed('expanded', expanded);
59540
59541
59542         var wrap = selection$$1.selectAll('div')
59543             .data([0]);
59544
59545         wrap = wrap.enter()
59546             .append('div')
59547             .merge(wrap);
59548
59549         wrap
59550             .classed('hide', !expanded)
59551             .call(content);
59552
59553
59554         function toggle() {
59555             expanded = !expanded;
59556             hideToggle.classed('expanded', expanded);
59557             wrap.call(uiToggle(expanded));
59558             dispatch$$1.call('toggled', this, expanded);
59559         }
59560     };
59561
59562
59563     disclosure.title = function(_) {
59564         if (!arguments.length) return title;
59565         title = _;
59566         return disclosure;
59567     };
59568
59569
59570     disclosure.expanded = function(_) {
59571         if (!arguments.length) return expanded;
59572         expanded = _;
59573         return disclosure;
59574     };
59575
59576
59577     disclosure.content = function(_) {
59578         if (!arguments.length) return content;
59579         content = _;
59580         return disclosure;
59581     };
59582
59583
59584     return utilRebind(disclosure, dispatch$$1, 'on');
59585 }
59586
59587 function uiRawMemberEditor(context) {
59588     var id,
59589         taginfo = services.taginfo;
59590
59591
59592     function selectMember(d) {
59593         event.preventDefault();
59594         context.enter(modeSelect(context, [d.id]));
59595     }
59596
59597
59598     function changeRole(d) {
59599         var role = select(this).property('value');
59600         var member = { id: d.id, type: d.type, role: role };
59601         context.perform(
59602             actionChangeMember(d.relation.id, member, d.index),
59603             t('operations.change_role.annotation')
59604         );
59605     }
59606
59607
59608     function deleteMember(d) {
59609         context.perform(
59610             actionDeleteMember(d.relation.id, d.index),
59611             t('operations.delete_member.annotation')
59612         );
59613
59614         if (!context.hasEntity(d.relation.id)) {
59615             context.enter(modeBrowse$$1(context));
59616         }
59617     }
59618
59619
59620     function rawMemberEditor(selection$$1) {
59621         var entity = context.entity(id),
59622             memberships = [];
59623
59624         entity.members.forEach(function(member, index) {
59625             memberships.push({
59626                 index: index,
59627                 id: member.id,
59628                 type: member.type,
59629                 role: member.role,
59630                 relation: entity,
59631                 member: context.hasEntity(member.id)
59632             });
59633         });
59634
59635         selection$$1.call(uiDisclosure()
59636             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
59637             .expanded(true)
59638             .on('toggled', toggled)
59639             .content(content)
59640         );
59641
59642
59643         function toggled(expanded) {
59644             if (expanded) {
59645                 selection$$1.node().parentNode.scrollTop += 200;
59646             }
59647         }
59648
59649
59650         function content(wrap) {
59651             var list = wrap.selectAll('.member-list')
59652                 .data([0]);
59653
59654             list = list.enter()
59655                 .append('ul')
59656                 .attr('class', 'member-list')
59657                 .merge(list);
59658
59659
59660             var items = list.selectAll('li')
59661                 .data(memberships, function(d) {
59662                     return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
59663                         (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
59664                 });
59665
59666             items.exit()
59667                 .each(unbind)
59668                 .remove();
59669
59670             var enter = items.enter()
59671                 .append('li')
59672                 .attr('class', 'member-row form-field')
59673                 .classed('member-incomplete', function(d) { return !d.member; });
59674
59675             enter
59676                 .each(function(d) {
59677                     if (d.member) {
59678                         var label = select(this).append('label')
59679                             .attr('class', 'form-label')
59680                             .append('a')
59681                             .attr('href', '#')
59682                             .on('click', selectMember);
59683
59684                         label.append('span')
59685                             .attr('class', 'member-entity-type')
59686                             .text(function(d) {
59687                                 var matched = context.presets().match(d.member, context.graph());
59688                                 return (matched && matched.name()) || utilDisplayType(d.member.id);
59689                             });
59690
59691                         label.append('span')
59692                             .attr('class', 'member-entity-name')
59693                             .text(function(d) { return utilDisplayName(d.member); });
59694
59695                     } else {
59696                         select(this).append('label')
59697                             .attr('class', 'form-label')
59698                             .text(t('inspector.incomplete', { id: d.id }));
59699                     }
59700                 });
59701
59702             enter
59703                 .append('input')
59704                 .attr('class', 'member-role')
59705                 .property('type', 'text')
59706                 .attr('maxlength', 255)
59707                 .attr('placeholder', t('inspector.role'))
59708                 .property('value', function(d) { return d.role; })
59709                 .on('change', changeRole);
59710
59711             enter
59712                 .append('button')
59713                 .attr('tabindex', -1)
59714                 .attr('class', 'remove button-input-action member-delete minor')
59715                 .on('click', deleteMember)
59716                 .call(svgIcon('#operation-delete'));
59717
59718             if (taginfo) {
59719                 enter.each(bindTypeahead);
59720             }
59721
59722
59723             function bindTypeahead(d) {
59724                 var row = select(this),
59725                     role = row.selectAll('input.member-role');
59726
59727                 function sort(value, data) {
59728                     var sameletter = [],
59729                         other = [];
59730                     for (var i = 0; i < data.length; i++) {
59731                         if (data[i].value.substring(0, value.length) === value) {
59732                             sameletter.push(data[i]);
59733                         } else {
59734                             other.push(data[i]);
59735                         }
59736                     }
59737                     return sameletter.concat(other);
59738                 }
59739
59740                 role.call(d3combobox()
59741                     .fetcher(function(role, callback) {
59742                         var rtype = entity.tags.type;
59743                         taginfo.roles({
59744                             debounce: true,
59745                             rtype: rtype || '',
59746                             geometry: context.geometry(d.member.id),
59747                             query: role
59748                         }, function(err, data) {
59749                             if (!err) callback(sort(role, data));
59750                         });
59751                     }));
59752             }
59753
59754
59755             function unbind() {
59756                 var row = select(this);
59757
59758                 row.selectAll('input.member-role')
59759                     .call(d3combobox.off);
59760             }
59761         }
59762     }
59763
59764
59765     rawMemberEditor.entityID = function(_) {
59766         if (!arguments.length) return id;
59767         id = _;
59768         return rawMemberEditor;
59769     };
59770
59771
59772     return rawMemberEditor;
59773 }
59774
59775 function uiRawMembershipEditor(context) {
59776     var taginfo = services.taginfo,
59777         id, showBlank;
59778
59779
59780     function selectRelation(d) {
59781         event.preventDefault();
59782         context.enter(modeSelect(context, [d.relation.id]));
59783     }
59784
59785
59786     function changeRole(d) {
59787         var role = select(this).property('value');
59788         context.perform(
59789             actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
59790             t('operations.change_role.annotation')
59791         );
59792     }
59793
59794
59795     function addMembership(d, role) {
59796         showBlank = false;
59797
59798         if (d.relation) {
59799             context.perform(
59800                 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
59801                 t('operations.add_member.annotation')
59802             );
59803
59804         } else {
59805             var relation = osmRelation();
59806             context.perform(
59807                 actionAddEntity(relation),
59808                 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
59809                 t('operations.add.annotation.relation')
59810             );
59811
59812             context.enter(modeSelect(context, [relation.id]));
59813         }
59814     }
59815
59816
59817     function deleteMembership(d) {
59818         context.perform(
59819             actionDeleteMember(d.relation.id, d.index),
59820             t('operations.delete_member.annotation')
59821         );
59822     }
59823
59824
59825     function relations(q) {
59826         var newRelation = {
59827                 relation: null,
59828                 value: t('inspector.new_relation')
59829             },
59830             result = [],
59831             graph = context.graph();
59832
59833         context.intersects(context.extent()).forEach(function(entity) {
59834             if (entity.type !== 'relation' || entity.id === id)
59835                 return;
59836
59837             var matched = context.presets().match(entity, graph),
59838                 presetName = (matched && matched.name()) || t('inspector.relation'),
59839                 entityName = utilDisplayName(entity) || '';
59840
59841             var value = presetName + ' ' + entityName;
59842             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
59843                 return;
59844
59845             result.push({
59846                 relation: entity,
59847                 value: value
59848             });
59849         });
59850
59851         result.sort(function(a, b) {
59852             return osmRelation.creationOrder(a.relation, b.relation);
59853         });
59854
59855         // Dedupe identical names by appending relation id - see #2891
59856         var dupeGroups = lodash(result)
59857             .groupBy('value')
59858             .filter(function(v) { return v.length > 1; })
59859             .value();
59860
59861         dupeGroups.forEach(function(group) {
59862             group.forEach(function(obj) {
59863                 obj.value += ' ' + obj.relation.id;
59864             });
59865         });
59866
59867         result.unshift(newRelation);
59868         return result;
59869     }
59870
59871
59872     function rawMembershipEditor(selection$$1) {
59873         var entity = context.entity(id),
59874             memberships = [];
59875
59876         context.graph().parentRelations(entity).forEach(function(relation) {
59877             relation.members.forEach(function(member, index) {
59878                 if (member.id === entity.id) {
59879                     memberships.push({ relation: relation, member: member, index: index });
59880                 }
59881             });
59882         });
59883
59884         selection$$1.call(uiDisclosure()
59885             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
59886             .expanded(true)
59887             .on('toggled', toggled)
59888             .content(content)
59889         );
59890
59891
59892         function toggled(expanded) {
59893             if (expanded) {
59894                 selection$$1.node().parentNode.scrollTop += 200;
59895             }
59896         }
59897
59898
59899         function content(wrap) {
59900             var list = wrap.selectAll('.member-list')
59901                 .data([0]);
59902
59903             list = list.enter()
59904                 .append('ul')
59905                 .attr('class', 'member-list')
59906                 .merge(list);
59907
59908
59909             var items = list.selectAll('li.member-row-normal')
59910                 .data(memberships, function(d) {
59911                     return osmEntity$$1.key(d.relation) + ',' + d.index;
59912                 });
59913
59914             items.exit()
59915                 .each(unbind)
59916                 .remove();
59917
59918             var enter = items.enter()
59919                 .append('li')
59920                 .attr('class', 'member-row member-row-normal form-field');
59921
59922             var label = enter
59923                 .append('label')
59924                 .attr('class', 'form-label')
59925                 .append('a')
59926                 .attr('href', '#')
59927                 .on('click', selectRelation);
59928
59929             label
59930                 .append('span')
59931                 .attr('class', 'member-entity-type')
59932                 .text(function(d) {
59933                     var matched = context.presets().match(d.relation, context.graph());
59934                     return (matched && matched.name()) || t('inspector.relation');
59935                 });
59936
59937             label
59938                 .append('span')
59939                 .attr('class', 'member-entity-name')
59940                 .text(function(d) { return utilDisplayName(d.relation); });
59941
59942             enter
59943                 .append('input')
59944                 .attr('class', 'member-role')
59945                 .property('type', 'text')
59946                 .attr('maxlength', 255)
59947                 .attr('placeholder', t('inspector.role'))
59948                 .property('value', function(d) { return d.member.role; })
59949                 .on('change', changeRole);
59950
59951             enter
59952                 .append('button')
59953                 .attr('tabindex', -1)
59954                 .attr('class', 'remove button-input-action member-delete minor')
59955                 .on('click', deleteMembership)
59956                 .call(svgIcon('#operation-delete'));
59957
59958             if (taginfo) {
59959                 enter.each(bindTypeahead);
59960             }
59961
59962
59963             var newrow = list.selectAll('.member-row-new')
59964                 .data(showBlank ? [0] : []);
59965
59966             newrow.exit()
59967                 .remove();
59968
59969             enter = newrow.enter()
59970                 .append('li')
59971                 .attr('class', 'member-row member-row-new form-field');
59972
59973             enter
59974                 .append('input')
59975                 .attr('type', 'text')
59976                 .attr('class', 'member-entity-input');
59977
59978             enter
59979                 .append('input')
59980                 .attr('class', 'member-role')
59981                 .property('type', 'text')
59982                 .attr('maxlength', 255)
59983                 .attr('placeholder', t('inspector.role'))
59984                 .on('change', changeRole);
59985
59986             enter
59987                 .append('button')
59988                 .attr('tabindex', -1)
59989                 .attr('class', 'remove button-input-action member-delete minor')
59990                 .on('click', deleteMembership)
59991                 .call(svgIcon('#operation-delete'));
59992
59993             newrow = newrow
59994                 .merge(enter);
59995
59996             newrow.selectAll('.member-entity-input')
59997                 .call(d3combobox()
59998                     .minItems(1)
59999                     .fetcher(function(value, callback) { callback(relations(value)); })
60000                     .on('accept', onAccept)
60001                 );
60002
60003
60004             var addrel = wrap.selectAll('.add-relation')
60005                 .data([0]);
60006
60007             addrel = addrel.enter()
60008                 .append('button')
60009                 .attr('class', 'add-relation')
60010                 .merge(addrel);
60011
60012             addrel
60013                 .call(svgIcon('#icon-plus', 'light'))
60014                 .on('click', function() {
60015                     showBlank = true;
60016                     content(wrap);
60017                     list.selectAll('.member-entity-input').node().focus();
60018                 });
60019
60020
60021             function onAccept(d) {
60022                 var role = list.selectAll('.member-row-new .member-role').property('value');
60023                 addMembership(d, role);
60024             }
60025
60026
60027             function bindTypeahead(d) {
60028                 var row = select(this),
60029                     role = row.selectAll('input.member-role');
60030
60031                 function sort(value, data) {
60032                     var sameletter = [],
60033                         other = [];
60034                     for (var i = 0; i < data.length; i++) {
60035                         if (data[i].value.substring(0, value.length) === value) {
60036                             sameletter.push(data[i]);
60037                         } else {
60038                             other.push(data[i]);
60039                         }
60040                     }
60041                     return sameletter.concat(other);
60042                 }
60043
60044                 role.call(d3combobox()
60045                     .fetcher(function(role, callback) {
60046                         var rtype = d.relation.tags.type;
60047                         taginfo.roles({
60048                             debounce: true,
60049                             rtype: rtype || '',
60050                             geometry: context.geometry(id),
60051                             query: role
60052                         }, function(err, data) {
60053                             if (!err) callback(sort(role, data));
60054                         });
60055                     }));
60056             }
60057
60058
60059             function unbind() {
60060                 var row = select(this);
60061
60062                 row.selectAll('input.member-role')
60063                     .call(d3combobox.off);
60064             }
60065         }
60066     }
60067
60068
60069     rawMembershipEditor.entityID = function(_) {
60070         if (!arguments.length) return id;
60071         id = _;
60072         return rawMembershipEditor;
60073     };
60074
60075
60076     return rawMembershipEditor;
60077 }
60078
60079 function uiTagReference(tag) {
60080     var taginfo = services.taginfo,
60081         tagReference = {},
60082         button,
60083         body,
60084         loaded,
60085         showing;
60086
60087
60088     function findLocal(data) {
60089         var locale = utilDetect().locale.toLowerCase(),
60090             localized;
60091
60092         localized = lodash.find(data, function(d) {
60093             return d.lang.toLowerCase() === locale;
60094         });
60095         if (localized) return localized;
60096
60097         // try the non-regional version of a language, like
60098         // 'en' if the language is 'en-US'
60099         if (locale.indexOf('-') !== -1) {
60100             var first = locale.split('-')[0];
60101             localized = lodash.find(data, function(d) {
60102                 return d.lang.toLowerCase() === first;
60103             });
60104             if (localized) return localized;
60105         }
60106
60107         // finally fall back to english
60108         return lodash.find(data, function(d) {
60109             return d.lang.toLowerCase() === 'en';
60110         });
60111     }
60112
60113
60114     function load(param) {
60115         if (!taginfo) return;
60116
60117         button.classed('tag-reference-loading', true);
60118
60119         taginfo.docs(param, function show(err, data) {
60120             var docs;
60121             if (!err && data) {
60122                 docs = findLocal(data);
60123             }
60124
60125             body.html('');
60126
60127
60128             if (!docs || !docs.title) {
60129                 if (param.hasOwnProperty('value')) {
60130                     load(lodash.omit(param, 'value'));   // retry with key only
60131                 } else {
60132                     body.append('p').text(t('inspector.no_documentation_key'));
60133                     done();
60134                 }
60135                 return;
60136             }
60137
60138
60139             if (docs.image && docs.image.thumb_url_prefix) {
60140                 body
60141                     .append('img')
60142                     .attr('class', 'wiki-image')
60143                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
60144                     .on('load', function() { done(); })
60145                     .on('error', function() { select(this).remove(); done(); });
60146             } else {
60147                 done();
60148             }
60149
60150             body
60151                 .append('p')
60152                 .text(docs.description || t('inspector.documentation_redirect'));
60153
60154             body
60155                 .append('a')
60156                 .attr('target', '_blank')
60157                 .attr('tabindex', -1)
60158                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
60159                 .call(svgIcon('#icon-out-link', 'inline'))
60160                 .append('span')
60161                 .text(t('inspector.reference'));
60162         });
60163     }
60164
60165
60166     function done() {
60167         loaded = true;
60168
60169         button.classed('tag-reference-loading', false);
60170
60171         body.transition()
60172             .duration(200)
60173             .style('max-height', '200px')
60174             .style('opacity', '1');
60175
60176         showing = true;
60177     }
60178
60179
60180     function hide(selection$$1) {
60181         selection$$1 = selection$$1 || body.transition().duration(200);
60182
60183         selection$$1
60184             .style('max-height', '0px')
60185             .style('opacity', '0');
60186
60187         showing = false;
60188     }
60189
60190
60191     tagReference.button = function(selection$$1) {
60192         button = selection$$1.selectAll('.tag-reference-button')
60193             .data([0]);
60194
60195         button = button.enter()
60196             .append('button')
60197             .attr('class', 'tag-reference-button')
60198             .attr('tabindex', -1)
60199             .call(svgIcon('#icon-inspect'))
60200             .merge(button);
60201
60202         button
60203             .on('click', function () {
60204                 event.stopPropagation();
60205                 event.preventDefault();
60206                 if (showing) {
60207                     hide();
60208                 } else if (loaded) {
60209                     done();
60210                 } else {
60211                     load(tag);
60212                 }
60213             });
60214     };
60215
60216
60217     tagReference.body = function(selection$$1) {
60218         body = selection$$1.selectAll('.tag-reference-body')
60219             .data([0]);
60220
60221         body = body.enter()
60222             .append('div')
60223             .attr('class', 'tag-reference-body cf')
60224             .style('max-height', '0')
60225             .style('opacity', '0')
60226             .merge(body);
60227
60228         if (showing === false) {
60229             hide(body);
60230         }
60231     };
60232
60233
60234     tagReference.showing = function(_) {
60235         if (!arguments.length) return showing;
60236         showing = _;
60237         return tagReference;
60238     };
60239
60240
60241     return tagReference;
60242 }
60243
60244 function uiRawTagEditor(context) {
60245     var taginfo = services.taginfo,
60246         dispatch$$1 = dispatch('change'),
60247         showBlank = false,
60248         state,
60249         preset,
60250         tags,
60251         id;
60252
60253
60254     function rawTagEditor(selection$$1) {
60255         var count = Object.keys(tags).filter(function(d) { return d; }).length;
60256
60257         selection$$1.call(uiDisclosure()
60258             .title(t('inspector.all_tags') + ' (' + count + ')')
60259             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
60260             .on('toggled', toggled)
60261             .content(content));
60262
60263         function toggled(expanded) {
60264             context.storage('raw_tag_editor.expanded', expanded);
60265             if (expanded) {
60266                 selection$$1.node().parentNode.scrollTop += 200;
60267             }
60268         }
60269     }
60270
60271
60272     function content(wrap) {
60273         var entries$$1 = entries(tags);
60274
60275         if (!entries$$1.length || showBlank) {
60276             showBlank = false;
60277             entries$$1.push({key: '', value: ''});
60278         }
60279
60280         var list = wrap.selectAll('.tag-list')
60281             .data([0]);
60282
60283         list = list.enter()
60284             .append('ul')
60285             .attr('class', 'tag-list')
60286             .merge(list);
60287
60288         var newTag = wrap.selectAll('.add-tag')
60289             .data([0]);
60290
60291         newTag.enter()
60292             .append('button')
60293             .attr('class', 'add-tag')
60294             .on('click', addTag)
60295             .call(svgIcon('#icon-plus', 'light'));
60296
60297
60298         var items = list.selectAll('.tag-row')
60299             .data(entries$$1, function(d) { return d.key; });
60300
60301         items.exit()
60302             .each(unbind)
60303             .remove();
60304
60305         // Enter
60306
60307         var enter = items.enter()
60308             .append('li')
60309             .attr('class', 'tag-row cf');
60310
60311         enter
60312             .append('div')
60313             .attr('class', 'key-wrap')
60314             .append('input')
60315             .property('type', 'text')
60316             .attr('class', 'key')
60317             .attr('maxlength', 255)
60318             .on('blur', keyChange)
60319             .on('change', keyChange);
60320
60321         enter
60322             .append('div')
60323             .attr('class', 'input-wrap-position')
60324             .append('input')
60325             .property('type', 'text')
60326             .attr('class', 'value')
60327             .attr('maxlength', 255)
60328             .on('blur', valueChange)
60329             .on('change', valueChange)
60330             .on('keydown.push-more', pushMore);
60331
60332         enter
60333             .append('button')
60334             .attr('tabindex', -1)
60335             .attr('class', 'remove minor')
60336             .call(svgIcon('#operation-delete'));
60337
60338
60339         // Update
60340
60341         items = items
60342             .merge(enter)
60343             .sort(function(a, b) {
60344                 return (a.key === '') ? 1
60345                     : (b.key === '') ? -1
60346                     : ascending(a.key, b.key);
60347             });
60348
60349         items
60350             .each(function(tag) {
60351                 var row = select(this),
60352                     key = row.select('input.key'),      // propagate bound data to child
60353                     value = row.select('input.value');  // propagate bound data to child
60354
60355                 if (taginfo) {
60356                     bindTypeahead(key, value);
60357                 }
60358
60359                 var isRelation = (context.entity(id).type === 'relation'),
60360                     reference;
60361
60362                 if (isRelation && tag.key === 'type') {
60363                     reference = uiTagReference({ rtype: tag.value }, context);
60364                 } else {
60365                     reference = uiTagReference({ key: tag.key, value: tag.value }, context);
60366                 }
60367
60368                 if (state === 'hover') {
60369                     reference.showing(false);
60370                 }
60371
60372                 row
60373                     .call(reference.button)
60374                     .call(reference.body);
60375             });
60376
60377         items.selectAll('input.key')
60378             .attr('title', function(d) { return d.key; })
60379             .call(utilGetSetValue, function(d) { return d.key; });
60380
60381         items.selectAll('input.value')
60382             .attr('title', function(d) { return d.value; })
60383             .call(utilGetSetValue, function(d) { return d.value; });
60384
60385         items.selectAll('button.remove')
60386             .on('click', removeTag);
60387
60388
60389         function pushMore() {
60390             if (event.keyCode === 9 && !event.shiftKey &&
60391                 list.selectAll('li:last-child input.value').node() === this) {
60392                 addTag();
60393             }
60394         }
60395
60396
60397         function bindTypeahead(key, value) {
60398
60399             function sort(value, data) {
60400                 var sameletter = [],
60401                     other = [];
60402                 for (var i = 0; i < data.length; i++) {
60403                     if (data[i].value.substring(0, value.length) === value) {
60404                         sameletter.push(data[i]);
60405                     } else {
60406                         other.push(data[i]);
60407                     }
60408                 }
60409                 return sameletter.concat(other);
60410             }
60411
60412             key.call(d3combobox()
60413                 .fetcher(function(value, callback) {
60414                     taginfo.keys({
60415                         debounce: true,
60416                         geometry: context.geometry(id),
60417                         query: value
60418                     }, function(err, data) {
60419                         if (!err) callback(sort(value, data));
60420                     });
60421                 }));
60422
60423             value.call(d3combobox()
60424                 .fetcher(function(value, callback) {
60425                     taginfo.values({
60426                         debounce: true,
60427                         key: utilGetSetValue(key),
60428                         geometry: context.geometry(id),
60429                         query: value
60430                     }, function(err, data) {
60431                         if (!err) callback(sort(value, data));
60432                     });
60433                 }));
60434         }
60435
60436
60437         function unbind() {
60438             var row = select(this);
60439
60440             row.selectAll('input.key')
60441                 .call(d3combobox.off);
60442
60443             row.selectAll('input.value')
60444                 .call(d3combobox.off);
60445         }
60446
60447
60448         function keyChange(d) {
60449             var kOld = d.key,
60450                 kNew = this.value.trim(),
60451                 tag = {};
60452
60453             if (kNew && kNew !== kOld) {
60454                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
60455                     base = match[1],
60456                     suffix = +(match[2] || 1);
60457                 while (tags[kNew]) {  // rename key if already in use
60458                     kNew = base + '_' + suffix++;
60459                 }
60460             }
60461             tag[kOld] = undefined;
60462             tag[kNew] = d.value;
60463             d.key = kNew; // Maintain DOM identity through the subsequent update.
60464             this.value = kNew;
60465             dispatch$$1.call('change', this, tag);
60466         }
60467
60468
60469         function valueChange(d) {
60470             var tag = {};
60471             tag[d.key] = this.value;
60472             dispatch$$1.call('change', this, tag);
60473         }
60474
60475
60476         function removeTag(d) {
60477             var tag = {};
60478             tag[d.key] = undefined;
60479             dispatch$$1.call('change', this, tag);
60480             select(this.parentNode).remove();
60481         }
60482
60483
60484         function addTag() {
60485             // Wrapped in a setTimeout in case it's being called from a blur
60486             // handler. Without the setTimeout, the call to `content` would
60487             // wipe out the pending value change.
60488             setTimeout(function() {
60489                 showBlank = true;
60490                 content(wrap);
60491                 list.selectAll('li:last-child input.key').node().focus();
60492             }, 0);
60493         }
60494     }
60495
60496
60497     rawTagEditor.state = function(_) {
60498         if (!arguments.length) return state;
60499         state = _;
60500         return rawTagEditor;
60501     };
60502
60503
60504     rawTagEditor.preset = function(_) {
60505         if (!arguments.length) return preset;
60506         preset = _;
60507         return rawTagEditor;
60508     };
60509
60510
60511     rawTagEditor.tags = function(_) {
60512         if (!arguments.length) return tags;
60513         tags = _;
60514         return rawTagEditor;
60515     };
60516
60517
60518     rawTagEditor.entityID = function(_) {
60519         if (!arguments.length) return id;
60520         id = _;
60521         return rawTagEditor;
60522     };
60523
60524
60525     return utilRebind(rawTagEditor, dispatch$$1, 'on');
60526 }
60527
60528 function uiFieldCheck(field) {
60529     var dispatch$$1 = dispatch('change'),
60530         options = field.strings && field.strings.options,
60531         values$$1 = [],
60532         texts = [],
60533         box = select(null),
60534         text$$1 = select(null),
60535         label = select(null),
60536         entity, value;
60537
60538     if (options) {
60539         for (var k in options) {
60540             values$$1.push(k === 'undefined' ? undefined : k);
60541             texts.push(field.t('options.' + k, { 'default': options[k] }));
60542         }
60543     } else {
60544         values$$1 = [undefined, 'yes'];
60545         texts = [t('inspector.unknown'), t('inspector.check.yes')];
60546         if (field.type === 'check') {
60547             values$$1.push('no');
60548             texts.push(t('inspector.check.no'));
60549         }
60550     }
60551
60552
60553     var check = function(selection$$1) {
60554         // hack: pretend oneway field is a oneway_yes field
60555         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
60556         if (field.id === 'oneway') {
60557             for (var key in entity.tags) {
60558                 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
60559                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
60560                     break;
60561                 }
60562             }
60563         }
60564
60565         selection$$1.classed('checkselect', 'true');
60566
60567         label = selection$$1.selectAll('.preset-input-wrap')
60568             .data([0]);
60569
60570         var enter = label.enter()
60571             .append('label')
60572             .attr('class', 'preset-input-wrap');
60573
60574         enter.append('input')
60575             .property('indeterminate', field.type === 'check')
60576             .attr('type', 'checkbox')
60577             .attr('id', 'preset-input-' + field.id)
60578             .on('click', function() {
60579                 var t$$1 = {};
60580                 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
60581                 dispatch$$1.call('change', this, t$$1);
60582                 event.stopPropagation();
60583             });
60584
60585         enter.append('span')
60586             .text(texts[0])
60587             .attr('class', 'value');
60588
60589         label = label.merge(enter);
60590
60591         box = label.selectAll('input');
60592         text$$1 = label.selectAll('span.value');
60593     };
60594
60595
60596     check.entity = function(_) {
60597         if (!arguments.length) return entity;
60598         entity = _;
60599         return check;
60600     };
60601
60602
60603     check.tags = function(tags) {
60604         value = tags[field.key];
60605         box.property('indeterminate', field.type === 'check' && !value);
60606         box.property('checked', value === 'yes');
60607         text$$1.text(texts[values$$1.indexOf(value)]);
60608         label.classed('set', !!value);
60609     };
60610
60611
60612     check.focus = function() {
60613         box.node().focus();
60614     };
60615
60616     return utilRebind(check, dispatch$$1, 'on');
60617 }
60618
60619 function uiFieldCombo(field, context) {
60620     var dispatch$$1 = dispatch('change'),
60621         nominatim = services.nominatim,
60622         taginfo = services.taginfo,
60623         isMulti = (field.type === 'multiCombo'),
60624         isNetwork = (field.type === 'networkCombo'),
60625         optstrings = field.strings && field.strings.options,
60626         optarray = field.options,
60627         snake_case = (field.snake_case || (field.snake_case === undefined)),
60628         combobox = d3combobox().minItems(isMulti ? 1 : 2),
60629         comboData = [],
60630         multiData = [],
60631         container,
60632         input,
60633         entity,
60634         country;
60635
60636     // ensure multiCombo field.key ends with a ':'
60637     if (isMulti && field.key.match(/:$/) === null) {
60638         field.key += ':';
60639     }
60640
60641
60642     function snake(s) {
60643         return s.replace(/\s+/g, '_');
60644     }
60645
60646     function unsnake(s) {
60647         return s.replace(/_+/g, ' ');
60648     }
60649
60650     function clean(s) {
60651         return s.split(';')
60652             .map(function(s) { return s.trim(); })
60653             .join(';');
60654     }
60655
60656
60657     // returns the tag value for a display value
60658     // (for multiCombo, dval should be the key suffix, not the entire key)
60659     function tagValue(dval) {
60660         dval = clean(dval || '');
60661
60662         if (optstrings) {
60663             var match = lodash.find(comboData, function(o) {
60664                 return o.key && clean(o.value) === dval;
60665             });
60666             if (match) {
60667                 return match.key;
60668             }
60669         }
60670
60671         if (field.type === 'typeCombo' && !dval) {
60672             return 'yes';
60673         }
60674
60675         return (snake_case ? snake(dval) : dval) || undefined;
60676     }
60677
60678
60679     // returns the display value for a tag value
60680     // (for multiCombo, tval should be the key suffix, not the entire key)
60681     function displayValue(tval) {
60682         tval = tval || '';
60683
60684         if (optstrings) {
60685             var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
60686             if (match) {
60687                 return match.value;
60688             }
60689         }
60690
60691         if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
60692             return '';
60693         }
60694
60695         return snake_case ? unsnake(tval) : tval;
60696     }
60697
60698
60699     function objectDifference(a, b) {
60700         return lodash.reject(a, function(d1) {
60701             return lodash.some(b, function(d2) { return d1.value === d2.value; });
60702         });
60703     }
60704
60705
60706     function initCombo(selection$$1, attachTo) {
60707         if (optstrings) {
60708             selection$$1.attr('readonly', 'readonly');
60709             selection$$1.call(combobox, attachTo);
60710             setStaticValues(setPlaceholder);
60711
60712         } else if (optarray) {
60713             selection$$1.call(combobox, attachTo);
60714             setStaticValues(setPlaceholder);
60715
60716         } else if (taginfo) {
60717             selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
60718             setTaginfoValues('', setPlaceholder);
60719         }
60720     }
60721
60722
60723     function setStaticValues(callback) {
60724         if (!(optstrings || optarray)) return;
60725
60726         if (optstrings) {
60727             comboData = Object.keys(optstrings).map(function(k) {
60728                 var v = field.t('options.' + k, { 'default': optstrings[k] });
60729                 return {
60730                     key: k,
60731                     value: v,
60732                     title: v
60733                 };
60734             });
60735
60736         } else if (optarray) {
60737             comboData = optarray.map(function(k) {
60738                 var v = snake_case ? unsnake(k) : k;
60739                 return {
60740                     key: k,
60741                     value: v,
60742                     title: v
60743                 };
60744             });
60745         }
60746
60747         combobox.data(objectDifference(comboData, multiData));
60748         if (callback) callback(comboData);
60749     }
60750
60751
60752     function setTaginfoValues(q, callback) {
60753         var fn = isMulti ? 'multikeys' : 'values';
60754         var query = (isMulti ? field.key : '') + q;
60755         var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
60756         if (hasCountryPrefix) {
60757             query = country + ':';
60758         }
60759         taginfo[fn]({
60760             debounce: true,
60761             key: field.key,
60762             geometry: context.geometry(entity.id),
60763             query: query
60764         }, function(err, data) {
60765             if (err) return;
60766             if (hasCountryPrefix) {
60767                 data = lodash.filter(data, function(d) {
60768                     return d.value.toLowerCase().indexOf(country + ':') === 0;
60769                 });
60770             }
60771             comboData = lodash.map(data, function(d) {
60772                 var k = d.value;
60773                 if (isMulti) k = k.replace(field.key, '');
60774                 var v = snake_case ? unsnake(k) : k;
60775                 return {
60776                     key: k,
60777                     value: v,
60778                     title: isMulti ? v : d.title
60779                 };
60780             });
60781             comboData = objectDifference(comboData, multiData);
60782             if (callback) callback(comboData);
60783         });
60784     }
60785
60786
60787     function setPlaceholder(d) {
60788         var ph;
60789         if (isMulti) {
60790             ph = field.placeholder() || t('inspector.add');
60791         } else {
60792             var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
60793                 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
60794             ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
60795         }
60796
60797         container.selectAll('input')
60798             .attr('placeholder', ph + '…');
60799     }
60800
60801
60802     function change() {
60803         var val = tagValue(utilGetSetValue(input)),
60804             t$$1 = {};
60805
60806         if (isMulti) {
60807             if (!val) return;
60808             container.classed('active', false);
60809             utilGetSetValue(input, '');
60810             field.keys.push(field.key + val);
60811             t$$1[field.key + val] = 'yes';
60812             window.setTimeout(function() { input.node().focus(); }, 10);
60813
60814         } else {
60815             t$$1[field.key] = val;
60816         }
60817
60818         dispatch$$1.call('change', this, t$$1);
60819     }
60820
60821
60822     function removeMultikey(d) {
60823         event.stopPropagation();
60824         var t$$1 = {};
60825         t$$1[d.key] = undefined;
60826         dispatch$$1.call('change', this, t$$1);
60827     }
60828
60829
60830     function combo(selection$$1) {
60831         if (isMulti) {
60832             container = selection$$1.selectAll('ul').data([0]);
60833
60834             container = container.enter()
60835                 .append('ul')
60836                 .attr('class', 'form-field-multicombo')
60837                 .on('click', function() {
60838                     window.setTimeout(function() { input.node().focus(); }, 10);
60839                 })
60840                 .merge(container);
60841
60842         } else {
60843             container = selection$$1;
60844         }
60845
60846         input = container.selectAll('input')
60847             .data([0]);
60848
60849         input = input.enter()
60850             .append('input')
60851             .attr('type', 'text')
60852             .attr('id', 'preset-input-' + field.id)
60853             .call(initCombo, selection$$1)
60854             .merge(input);
60855
60856         if (isNetwork && nominatim && entity) {
60857             var center = entity.extent(context.graph()).center();
60858             nominatim.countryCode(center, function (err, code) {
60859                 country = code;
60860             });
60861         }
60862
60863         input
60864             .on('change', change)
60865             .on('blur', change);
60866
60867         if (isMulti) {
60868             combobox
60869                 .on('accept', function() {
60870                     input.node().blur();
60871                     input.node().focus();
60872                 });
60873
60874             input
60875                 .on('focus', function() { container.classed('active', true); });
60876         }
60877     }
60878
60879
60880     combo.tags = function(tags) {
60881         if (isMulti) {
60882             multiData = [];
60883
60884             // Build multiData array containing keys already set..
60885             Object.keys(tags).forEach(function(key) {
60886                 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
60887
60888                 var suffix = key.substring(field.key.length);
60889                 multiData.push({
60890                     key: key,
60891                     value: displayValue(suffix)
60892                 });
60893             });
60894
60895             // Set keys for form-field modified (needed for undo and reset buttons)..
60896             field.keys = lodash.map(multiData, 'key');
60897
60898             // Exclude existing multikeys from combo options..
60899             var available = objectDifference(comboData, multiData);
60900             combobox.data(available);
60901
60902             // Hide 'Add' button if this field uses fixed set of
60903             // translateable optstrings and they're all currently used..
60904             container.selectAll('.combobox-input, .combobox-caret')
60905                 .classed('hide', optstrings && !available.length);
60906
60907
60908             // Render chips
60909             var chips = container.selectAll('.chips')
60910                 .data(multiData);
60911
60912             chips.exit()
60913                 .remove();
60914
60915             var enter = chips.enter()
60916                 .insert('li', 'input')
60917                 .attr('class', 'chips');
60918
60919             enter.append('span');
60920             enter.append('a');
60921
60922             chips = chips.merge(enter);
60923
60924             chips.select('span')
60925                 .text(function(d) { return d.value; });
60926
60927             chips.select('a')
60928                 .on('click', removeMultikey)
60929                 .attr('class', 'remove')
60930                 .text('×');
60931
60932         } else {
60933             utilGetSetValue(input, displayValue(tags[field.key]));
60934         }
60935     };
60936
60937
60938     combo.focus = function() {
60939         input.node().focus();
60940     };
60941
60942
60943     combo.entity = function(_) {
60944         if (!arguments.length) return entity;
60945         entity = _;
60946         return combo;
60947     };
60948
60949
60950     return utilRebind(combo, dispatch$$1, 'on');
60951 }
60952
60953 function uiFieldText(field, context) {
60954     var dispatch$$1 = dispatch('change'),
60955         nominatim = services.nominatim,
60956         input,
60957         entity;
60958
60959
60960     function i(selection$$1) {
60961         var fieldId = 'preset-input-' + field.id;
60962
60963         input = selection$$1.selectAll('input')
60964             .data([0]);
60965
60966         input = input.enter()
60967             .append('input')
60968             .attr('type', field.type)
60969             .attr('id', fieldId)
60970             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
60971             .merge(input);
60972
60973         input
60974             .on('input', change(true))
60975             .on('blur', change())
60976             .on('change', change());
60977
60978         if (field.type === 'tel' && nominatim && entity) {
60979             var center = entity.extent(context.graph()).center();
60980             nominatim.countryCode(center, function (err, countryCode) {
60981                 if (err || !dataPhoneFormats[countryCode]) return;
60982                 selection$$1.selectAll('#' + fieldId)
60983                     .attr('placeholder', dataPhoneFormats[countryCode]);
60984             });
60985
60986         } else if (field.type === 'number') {
60987             input.attr('type', 'text');
60988
60989             var spinControl = selection$$1.selectAll('.spin-control')
60990                 .data([0]);
60991
60992             var enter = spinControl.enter()
60993                 .append('div')
60994                 .attr('class', 'spin-control');
60995
60996             enter
60997                 .append('button')
60998                 .datum(1)
60999                 .attr('class', 'increment')
61000                 .attr('tabindex', -1);
61001
61002             enter
61003                 .append('button')
61004                 .datum(-1)
61005                 .attr('class', 'decrement')
61006                 .attr('tabindex', -1);
61007
61008             spinControl = spinControl
61009                 .merge(enter);
61010
61011             spinControl.selectAll('button')
61012                 .on('click', function(d) {
61013                     event.preventDefault();
61014                     var num = parseInt(input.node().value || 0, 10);
61015                     if (!isNaN(num)) input.node().value = num + d;
61016                     change()();
61017                 });
61018         }
61019     }
61020
61021
61022     function change(onInput) {
61023         return function() {
61024             var t$$1 = {};
61025             t$$1[field.key] = utilGetSetValue(input) || undefined;
61026             dispatch$$1.call('change', this, t$$1, onInput);
61027         };
61028     }
61029
61030
61031     i.entity = function(_) {
61032         if (!arguments.length) return entity;
61033         entity = _;
61034         return i;
61035     };
61036
61037
61038     i.tags = function(tags) {
61039         utilGetSetValue(input, tags[field.key] || '');
61040     };
61041
61042
61043     i.focus = function() {
61044         var node = input.node();
61045         if (node) node.focus();
61046     };
61047
61048     return utilRebind(i, dispatch$$1, 'on');
61049 }
61050
61051 function uiFieldAccess(field) {
61052     var dispatch$$1 = dispatch('change'),
61053         items;
61054
61055     function access(selection$$1) {
61056         var wrap = selection$$1.selectAll('.preset-input-wrap')
61057             .data([0]);
61058
61059         wrap = wrap.enter()
61060             .append('div')
61061             .attr('class', 'cf preset-input-wrap')
61062             .append('ul')
61063             .merge(wrap);
61064
61065         var list = wrap.selectAll('ul')
61066             .data([0]);
61067
61068         list = list.enter()
61069             .append('ul')
61070             .merge(list);
61071
61072
61073         items = list.selectAll('li')
61074             .data(field.keys);
61075
61076         // Enter
61077         var enter = items.enter()
61078             .append('li')
61079             .attr('class', function(d) { return 'cf preset-access-' + d; });
61080
61081         enter
61082             .append('span')
61083             .attr('class', 'col6 label preset-label-access')
61084             .attr('for', function(d) { return 'preset-input-access-' + d; })
61085             .text(function(d) { return field.t('types.' + d); });
61086
61087         enter
61088             .append('div')
61089             .attr('class', 'col6 preset-input-access-wrap')
61090             .append('input')
61091             .attr('type', 'text')
61092             .attr('class', 'preset-input-access')
61093             .attr('id', function(d) { return 'preset-input-access-' + d; })
61094             .each(function(d) {
61095                 select(this)
61096                     .call(d3combobox()
61097                         .data(access.options(d)));
61098             });
61099
61100
61101         // Update
61102         items = items.merge(enter);
61103
61104         wrap.selectAll('.preset-input-access')
61105             .on('change', change)
61106             .on('blur', change);
61107     }
61108
61109
61110     function change(d) {
61111         var tag = {};
61112         tag[d] = utilGetSetValue(select(this)) || undefined;
61113         dispatch$$1.call('change', this, tag);
61114     }
61115
61116
61117     access.options = function(type) {
61118         var options = ['no', 'permissive', 'private', 'destination'];
61119
61120         if (type !== 'access') {
61121             options.unshift('yes');
61122             options.push('designated');
61123
61124             if (type === 'bicycle') {
61125                 options.push('dismount');
61126             }
61127         }
61128
61129         return options.map(function(option) {
61130             return {
61131                 title: field.t('options.' + option + '.description'),
61132                 value: option
61133             };
61134         });
61135     };
61136
61137
61138     var placeholders = {
61139         footway: {
61140             foot: 'designated',
61141             motor_vehicle: 'no'
61142         },
61143         steps: {
61144             foot: 'yes',
61145             motor_vehicle: 'no',
61146             bicycle: 'no',
61147             horse: 'no'
61148         },
61149         pedestrian: {
61150             foot: 'yes',
61151             motor_vehicle: 'no'
61152         },
61153         cycleway: {
61154             motor_vehicle: 'no',
61155             bicycle: 'designated'
61156         },
61157         bridleway: {
61158             motor_vehicle: 'no',
61159             horse: 'designated'
61160         },
61161         path: {
61162             foot: 'yes',
61163             motor_vehicle: 'no',
61164             bicycle: 'yes',
61165             horse: 'yes'
61166         },
61167         motorway: {
61168             foot: 'no',
61169             motor_vehicle: 'yes',
61170             bicycle: 'no',
61171             horse: 'no'
61172         },
61173         trunk: {
61174             motor_vehicle: 'yes'
61175         },
61176         primary: {
61177             foot: 'yes',
61178             motor_vehicle: 'yes',
61179             bicycle: 'yes',
61180             horse: 'yes'
61181         },
61182         secondary: {
61183             foot: 'yes',
61184             motor_vehicle: 'yes',
61185             bicycle: 'yes',
61186             horse: 'yes'
61187         },
61188         tertiary: {
61189             foot: 'yes',
61190             motor_vehicle: 'yes',
61191             bicycle: 'yes',
61192             horse: 'yes'
61193         },
61194         residential: {
61195             foot: 'yes',
61196             motor_vehicle: 'yes',
61197             bicycle: 'yes',
61198             horse: 'yes'
61199         },
61200         unclassified: {
61201             foot: 'yes',
61202             motor_vehicle: 'yes',
61203             bicycle: 'yes',
61204             horse: 'yes'
61205         },
61206         service: {
61207             foot: 'yes',
61208             motor_vehicle: 'yes',
61209             bicycle: 'yes',
61210             horse: 'yes'
61211         },
61212         motorway_link: {
61213             foot: 'no',
61214             motor_vehicle: 'yes',
61215             bicycle: 'no',
61216             horse: 'no'
61217         },
61218         trunk_link: {
61219             motor_vehicle: 'yes'
61220         },
61221         primary_link: {
61222             foot: 'yes',
61223             motor_vehicle: 'yes',
61224             bicycle: 'yes',
61225             horse: 'yes'
61226         },
61227         secondary_link: {
61228             foot: 'yes',
61229             motor_vehicle: 'yes',
61230             bicycle: 'yes',
61231             horse: 'yes'
61232         },
61233         tertiary_link: {
61234             foot: 'yes',
61235             motor_vehicle: 'yes',
61236             bicycle: 'yes',
61237             horse: 'yes'
61238         }
61239     };
61240
61241
61242     access.tags = function(tags) {
61243         utilGetSetValue(items.selectAll('.preset-input-access'),
61244             function(d) { return tags[d] || ''; })
61245             .attr('placeholder', function() {
61246                 return tags.access ? tags.access : field.placeholder();
61247             });
61248
61249         items.selectAll('#preset-input-access-access')
61250             .attr('placeholder', 'yes');
61251
61252         lodash.forEach(placeholders[tags.highway], function(v, k) {
61253             items.selectAll('#preset-input-access-' + k)
61254                 .attr('placeholder', function() { return (tags.access || v); });
61255         });
61256     };
61257
61258
61259     access.focus = function() {
61260         items.selectAll('.preset-input-access')
61261             .node().focus();
61262     };
61263
61264
61265     return utilRebind(access, dispatch$$1, 'on');
61266 }
61267
61268 function uiFieldAddress(field, context) {
61269     var dispatch$$1 = dispatch('init', 'change'),
61270         nominatim = services.nominatim,
61271         wrap = select(null),
61272         isInitialized = false,
61273         entity;
61274
61275     var widths = {
61276         housenumber: 1/3,
61277         street: 2/3,
61278         city: 2/3,
61279         state: 1/4,
61280         postcode: 1/3
61281     };
61282
61283
61284     function getNearStreets() {
61285         var extent$$1 = entity.extent(context.graph()),
61286             l = extent$$1.center(),
61287             box = geoExtent$$1(l).padByMeters(200);
61288
61289         var streets = context.intersects(box)
61290             .filter(isAddressable)
61291             .map(function(d) {
61292                 var loc = context.projection([
61293                     (extent$$1[0][0] + extent$$1[1][0]) / 2,
61294                     (extent$$1[0][1] + extent$$1[1][1]) / 2]),
61295                     choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
61296                 return {
61297                     title: d.tags.name,
61298                     value: d.tags.name,
61299                     dist: choice.distance
61300                 };
61301             })
61302             .sort(function(a, b) {
61303                 return a.dist - b.dist;
61304             });
61305
61306         return lodash.uniqBy(streets, 'value');
61307
61308         function isAddressable(d) {
61309             return d.tags.highway && d.tags.name && d.type === 'way';
61310         }
61311     }
61312
61313
61314     function getNearCities() {
61315         var extent$$1 = entity.extent(context.graph()),
61316             l = extent$$1.center(),
61317             box = geoExtent$$1(l).padByMeters(200);
61318
61319         var cities = context.intersects(box)
61320             .filter(isAddressable)
61321             .map(function(d) {
61322                 return {
61323                     title: d.tags['addr:city'] || d.tags.name,
61324                     value: d.tags['addr:city'] || d.tags.name,
61325                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
61326                 };
61327             })
61328             .sort(function(a, b) {
61329                 return a.dist - b.dist;
61330             });
61331
61332         return lodash.uniqBy(cities, 'value');
61333
61334
61335         function isAddressable(d) {
61336             if (d.tags.name &&
61337                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
61338                 return true;
61339
61340             if (d.tags.place && d.tags.name && (
61341                     d.tags.place === 'city' ||
61342                     d.tags.place === 'town' ||
61343                     d.tags.place === 'village'))
61344                 return true;
61345
61346             if (d.tags['addr:city']) return true;
61347
61348             return false;
61349         }
61350     }
61351
61352
61353     function getNearValues(key) {
61354         var extent$$1 = entity.extent(context.graph()),
61355             l = extent$$1.center(),
61356             box = geoExtent$$1(l).padByMeters(200);
61357
61358         var results = context.intersects(box)
61359             .filter(function hasTag(d) {
61360                 return d.tags[key];
61361             })
61362             .map(function(d) {
61363                 return {
61364                     title: d.tags[key],
61365                     value: d.tags[key],
61366                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
61367                 };
61368             })
61369             .sort(function(a, b) {
61370                 return a.dist - b.dist;
61371             });
61372
61373         return lodash.uniqBy(results, 'value');
61374     }
61375
61376
61377     function initCallback(err, countryCode) {
61378         if (err) return;
61379
61380         var addressFormat = lodash.find(dataAddressFormats, function (a) {
61381             return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode);
61382         }) || lodash.first(dataAddressFormats);
61383
61384         function row(r) {
61385             // Normalize widths.
61386             var total = lodash.reduce(r, function(sum$$1, field) {
61387                 return sum$$1 + (widths[field] || 0.5);
61388             }, 0);
61389
61390             return r.map(function (field) {
61391                 return {
61392                     id: field,
61393                     width: (widths[field] || 0.5) / total
61394                 };
61395             });
61396         }
61397
61398         wrap.selectAll('div')
61399             .data(addressFormat.format)
61400             .enter()
61401             .append('div')
61402             .attr('class', 'addr-row')
61403             .selectAll('input')
61404             .data(row)
61405             .enter()
61406             .append('input')
61407             .property('type', 'text')
61408             .attr('placeholder', function (d) { return field.t('placeholders.' + d.id); })
61409             .attr('class', function (d) { return 'addr-' + d.id; })
61410             .style('width', function (d) { return d.width * 100 + '%'; });
61411
61412         // Update
61413         // setup dropdowns for common address tags
61414         var addrTags = [
61415             'street', 'city', 'state', 'province', 'district',
61416             'subdistrict', 'suburb', 'place', 'postcode'
61417         ];
61418
61419         addrTags.forEach(function(tag) {
61420             var nearValues = (tag === 'street') ? getNearStreets
61421                     : (tag === 'city') ? getNearCities
61422                     : getNearValues;
61423
61424             wrap.selectAll('.addr-' + tag)
61425                 .call(d3combobox()
61426                     .minItems(1)
61427                     .fetcher(function(value, callback) {
61428                         callback(nearValues('addr:' + tag));
61429                     }));
61430         });
61431
61432         wrap.selectAll('input')
61433             .on('blur', change())
61434             .on('change', change());
61435
61436         wrap.selectAll('input:not(.combobox-input)')
61437             .on('input', change(true));
61438
61439         dispatch$$1.call('init');
61440         isInitialized = true;
61441     }
61442
61443
61444     function address(selection$$1) {
61445         isInitialized = false;
61446
61447         wrap = selection$$1.selectAll('.preset-input-wrap')
61448             .data([0]);
61449
61450         wrap = wrap.enter()
61451             .append('div')
61452             .attr('class', 'preset-input-wrap')
61453             .merge(wrap);
61454
61455
61456         if (nominatim && entity) {
61457             var center = entity.extent(context.graph()).center();
61458             nominatim.countryCode(center, initCallback);
61459         }
61460     }
61461
61462
61463     function change(onInput) {
61464         return function() {
61465             var tags = {};
61466
61467             wrap.selectAll('input')
61468                 .each(function (field) {
61469                     tags['addr:' + field.id] = this.value || undefined;
61470                 });
61471
61472             dispatch$$1.call('change', this, tags, onInput);
61473         };
61474     }
61475
61476
61477     function updateTags(tags) {
61478         utilGetSetValue(wrap.selectAll('input'), function (field) {
61479             return tags['addr:' + field.id] || '';
61480         });
61481     }
61482
61483
61484     address.entity = function(_) {
61485         if (!arguments.length) return entity;
61486         entity = _;
61487         return address;
61488     };
61489
61490
61491     address.tags = function(tags) {
61492         if (isInitialized) {
61493             updateTags(tags);
61494         } else {
61495             dispatch$$1.on('init', function () {
61496                 updateTags(tags);
61497             });
61498         }
61499     };
61500
61501
61502     address.focus = function() {
61503         var node = wrap.selectAll('input').node();
61504         if (node) node.focus();
61505     };
61506
61507
61508     return utilRebind(address, dispatch$$1, 'on');
61509 }
61510
61511 function uiFieldCycleway(field) {
61512     var dispatch$$1 = dispatch('change'),
61513         items = select(null);
61514
61515
61516     function cycleway(selection$$1) {
61517
61518         function stripcolon(s) {
61519             return s.replace(':', '');
61520         }
61521
61522
61523         var wrap = selection$$1.selectAll('.preset-input-wrap')
61524             .data([0]);
61525
61526         wrap = wrap.enter()
61527             .append('div')
61528             .attr('class', 'cf preset-input-wrap')
61529             .merge(wrap);
61530
61531
61532         var div = wrap.selectAll('ul')
61533             .data([0]);
61534
61535         div = div.enter()
61536             .append('ul')
61537             .merge(div);
61538
61539
61540         items = div.selectAll('li')
61541             .data(field.keys);
61542
61543         var enter = items.enter()
61544             .append('li')
61545             .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
61546
61547         enter
61548             .append('span')
61549             .attr('class', 'col6 label preset-label-cycleway')
61550             .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
61551             .text(function(d) { return field.t('types.' + d); });
61552
61553         enter
61554             .append('div')
61555             .attr('class', 'col6 preset-input-cycleway-wrap')
61556             .append('input')
61557             .attr('type', 'text')
61558             .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
61559             .each(function(d) {
61560                 select(this).call(d3combobox().data(cycleway.options(d)));
61561             });
61562
61563
61564         // Update
61565         wrap.selectAll('.preset-input-cycleway')
61566             .on('change', change)
61567             .on('blur', change);
61568     }
61569
61570
61571     function change() {
61572         var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
61573             right = utilGetSetValue(select('.preset-input-cyclewayright')),
61574             tag = {};
61575
61576         if (left === 'none' || left === '') { left = undefined; }
61577         if (right === 'none' || right === '') { right = undefined; }
61578
61579         // Always set both left and right as changing one can affect the other
61580         tag = {
61581             cycleway: undefined,
61582             'cycleway:left': left,
61583             'cycleway:right': right
61584         };
61585
61586         // If the left and right tags match, use the cycleway tag to tag both
61587         // sides the same way
61588         if (left === right) {
61589             tag = {
61590                 cycleway: left,
61591                 'cycleway:left': undefined,
61592                 'cycleway:right': undefined
61593             };
61594         }
61595
61596         dispatch$$1.call('change', this, tag);
61597     }
61598
61599
61600     cycleway.options = function() {
61601         return keys(field.strings.options).map(function(option) {
61602             return {
61603                 title: field.t('options.' + option + '.description'),
61604                 value: option
61605             };
61606         });
61607     };
61608
61609
61610     cycleway.tags = function(tags) {
61611         utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
61612                 // If cycleway is set, always return that
61613                 if (tags.cycleway) {
61614                     return tags.cycleway;
61615                 }
61616                 return tags[d] || '';
61617             })
61618             .attr('placeholder', field.placeholder());
61619     };
61620
61621
61622     cycleway.focus = function() {
61623         items.selectAll('.preset-input-cycleway')
61624             .node().focus();
61625     };
61626
61627
61628     return utilRebind(cycleway, dispatch$$1, 'on');
61629 }
61630
61631 function uiFieldLanes(field, context) {
61632     var dispatch$$1 = dispatch('change'),
61633         LANE_WIDTH = 40,
61634         LANE_HEIGHT = 200,
61635         wayID,
61636         lanesData;
61637
61638     function lanes(selection$$1) {
61639         lanesData = context.entity(wayID).lanes();
61640
61641         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
61642             selection$$1.call(lanes.off);
61643             return;
61644         }
61645
61646         var wrap = selection$$1.selectAll('.preset-input-wrap')
61647             .data([0]);
61648
61649         wrap = wrap.enter()
61650             .append('div')
61651             .attr('class', 'preset-input-wrap')
61652             .merge(wrap);
61653
61654         var surface =  wrap.selectAll('.surface')
61655             .data([0]);
61656
61657         var d = utilGetDimensions(wrap);
61658         var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
61659
61660         surface = surface.enter()
61661             .append('svg')
61662             .attr('width', d[0])
61663             .attr('height', 300)
61664             .attr('class', 'surface')
61665             .merge(surface);
61666
61667
61668         var lanesSelection = surface.selectAll('.lanes')
61669             .data([0]);
61670
61671         lanesSelection = lanesSelection.enter()
61672             .append('g')
61673             .attr('class', 'lanes')
61674             .merge(lanesSelection);
61675
61676         lanesSelection
61677             .attr('transform', function () {
61678                 return 'translate(' + (freeSpace / 2) + ', 0)';
61679             });
61680
61681
61682         var lane = lanesSelection.selectAll('.lane')
61683            .data(lanesData.lanes);
61684
61685         lane.exit()
61686             .remove();
61687
61688         var enter = lane.enter()
61689             .append('g')
61690             .attr('class', 'lane');
61691
61692         enter
61693             .append('g')
61694             .append('rect')
61695             .attr('y', 50)
61696             .attr('width', LANE_WIDTH)
61697             .attr('height', LANE_HEIGHT);
61698
61699         enter
61700             .append('g')
61701             .attr('class', 'forward')
61702             .append('text')
61703             .attr('y', 40)
61704             .attr('x', 14)
61705             .text('▲');
61706
61707         enter
61708             .append('g')
61709             .attr('class', 'bothways')
61710             .append('text')
61711             .attr('y', 40)
61712             .attr('x', 14)
61713             .text('▲▼');
61714
61715         enter
61716             .append('g')
61717             .attr('class', 'backward')
61718             .append('text')
61719             .attr('y', 40)
61720             .attr('x', 14)
61721             .text('▼');
61722
61723
61724         lane = lane
61725             .merge(enter);
61726
61727         lane
61728             .attr('transform', function(d) {
61729                 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
61730             });
61731
61732         lane.select('.forward')
61733             .style('visibility', function(d) {
61734                 return d.direction === 'forward' ? 'visible' : 'hidden';
61735             });
61736
61737         lane.select('.bothways')
61738             .style('visibility', function(d) {
61739                 return d.direction === 'bothways' ? 'visible' : 'hidden';
61740             });
61741
61742         lane.select('.backward')
61743             .style('visibility', function(d) {
61744                 return d.direction === 'backward' ? 'visible' : 'hidden';
61745             });
61746     }
61747
61748
61749     lanes.entity = function(_) {
61750         if (!wayID || wayID !== _.id) {
61751             wayID = _.id;
61752         }
61753     };
61754
61755     lanes.tags = function() {};
61756     lanes.focus = function() {};
61757     lanes.off = function() {};
61758
61759     return utilRebind(lanes, dispatch$$1, 'on');
61760 }
61761
61762 function uiFieldLocalized(field, context) {
61763     var dispatch$$1 = dispatch('change', 'input'),
61764         wikipedia = services.wikipedia,
61765         input = select(null),
61766         localizedInputs = select(null),
61767         wikiTitles,
61768         entity;
61769
61770
61771     function localized(selection$$1) {
61772         input = selection$$1.selectAll('.localized-main')
61773             .data([0]);
61774
61775         input = input.enter()
61776             .append('input')
61777             .attr('type', 'text')
61778             .attr('id', 'preset-input-' + field.id)
61779             .attr('class', 'localized-main')
61780             .attr('placeholder', field.placeholder())
61781             .merge(input);
61782
61783         if (field.id === 'name') {
61784             var preset = context.presets().match(entity, context.graph());
61785             input.call(d3combobox().fetcher(
61786                 utilSuggestNames(preset, dataSuggestions)
61787             ));
61788         }
61789
61790         input
61791             .on('input', change(true))
61792             .on('blur', change())
61793             .on('change', change());
61794
61795
61796         var translateButton = selection$$1.selectAll('.localized-add')
61797             .data([0]);
61798
61799         translateButton = translateButton.enter()
61800             .append('button')
61801             .attr('class', 'button-input-action localized-add minor')
61802             .attr('tabindex', -1)
61803             .call(svgIcon('#icon-plus'))
61804             .call(tooltip()
61805                 .title(t('translate.translate'))
61806                 .placement('left'))
61807             .merge(translateButton);
61808
61809         translateButton
61810             .on('click', addNew);
61811
61812
61813         localizedInputs = selection$$1.selectAll('.localized-wrap')
61814             .data([0]);
61815
61816         localizedInputs = localizedInputs.enter().append('div')
61817             .attr('class', 'localized-wrap')
61818             .merge(localizedInputs);
61819     }
61820
61821
61822     function addNew() {
61823         event.preventDefault();
61824         var data$$1 = localizedInputs.selectAll('div.entry').data();
61825         var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
61826         var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
61827         var isLangEn = defaultLang.indexOf('en') > -1;
61828         if (isLangEn || langExists) {
61829             defaultLang = '';
61830         }
61831         data$$1.push({ lang: defaultLang, value: '' });
61832         localizedInputs.call(render, data$$1);
61833     }
61834
61835
61836     function change(onInput) {
61837         return function() {
61838             var t$$1 = {};
61839             t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
61840             dispatch$$1.call('change', this, t$$1, onInput);
61841         };
61842     }
61843
61844
61845     function key(lang) {
61846         return field.key + ':' + lang;
61847     }
61848
61849
61850     function changeLang(d) {
61851         var lang = utilGetSetValue(select(this)),
61852             t$$1 = {},
61853             language = lodash.find(dataWikipedia, function(d) {
61854                 return d[0].toLowerCase() === lang.toLowerCase() ||
61855                     d[1].toLowerCase() === lang.toLowerCase();
61856             });
61857
61858         if (language) lang = language[2];
61859
61860         if (d.lang && d.lang !== lang) {
61861             t$$1[key(d.lang)] = undefined;
61862         }
61863
61864         var value = utilGetSetValue(select(this.parentNode)
61865             .selectAll('.localized-value'));
61866
61867         if (lang && value) {
61868             t$$1[key(lang)] = value;
61869         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
61870             t$$1[key(lang)] = wikiTitles[d.lang];
61871         }
61872
61873         d.lang = lang;
61874         dispatch$$1.call('change', this, t$$1);
61875     }
61876
61877
61878     function changeValue(d) {
61879         if (!d.lang) return;
61880         var t$$1 = {};
61881         t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
61882         dispatch$$1.call('change', this, t$$1);
61883     }
61884
61885
61886     function fetcher(value, cb) {
61887         var v = value.toLowerCase();
61888
61889         cb(dataWikipedia.filter(function(d) {
61890             return d[0].toLowerCase().indexOf(v) >= 0 ||
61891             d[1].toLowerCase().indexOf(v) >= 0 ||
61892             d[2].toLowerCase().indexOf(v) >= 0;
61893         }).map(function(d) {
61894             return { value: d[1] };
61895         }));
61896     }
61897
61898
61899     function render(selection$$1, data$$1) {
61900         var wraps = selection$$1.selectAll('div.entry').
61901             data(data$$1, function(d) { return d.lang; });
61902
61903         wraps.exit()
61904             .transition()
61905             .duration(200)
61906             .style('max-height','0px')
61907             .style('opacity', '0')
61908             .style('top','-10px')
61909             .remove();
61910
61911         var innerWrap = wraps.enter()
61912             .insert('div', ':first-child');
61913
61914         innerWrap.attr('class', 'entry')
61915             .each(function() {
61916                 var wrap = select(this);
61917                 var langcombo = d3combobox().fetcher(fetcher).minItems(0);
61918
61919                 var label = wrap
61920                     .append('label')
61921                     .attr('class','form-label')
61922                     .text(t('translate.localized_translation_label'))
61923                     .attr('for','localized-lang');
61924
61925                 label
61926                     .append('button')
61927                     .attr('class', 'minor remove')
61928                     .on('click', function(d){
61929                         event.preventDefault();
61930                         var t$$1 = {};
61931                         t$$1[key(d.lang)] = undefined;
61932                         dispatch$$1.call('change', this, t$$1);
61933                         select(this.parentNode.parentNode)
61934                             .style('top','0')
61935                             .style('max-height','240px')
61936                             .transition()
61937                             .style('opacity', '0')
61938                             .style('max-height','0px')
61939                             .remove();
61940                     })
61941                     .call(svgIcon('#operation-delete'));
61942
61943                 wrap
61944                     .append('input')
61945                     .attr('class', 'localized-lang')
61946                     .attr('type', 'text')
61947                     .attr('placeholder',t('translate.localized_translation_language'))
61948                     .on('blur', changeLang)
61949                     .on('change', changeLang)
61950                     .call(langcombo);
61951
61952                 wrap
61953                     .append('input')
61954                     .on('blur', changeValue)
61955                     .on('change', changeValue)
61956                     .attr('type', 'text')
61957                     .attr('placeholder', t('translate.localized_translation_name'))
61958                     .attr('class', 'localized-value');
61959             });
61960
61961         innerWrap
61962             .style('margin-top', '0px')
61963             .style('max-height', '0px')
61964             .style('opacity', '0')
61965             .transition()
61966             .duration(200)
61967             .style('margin-top', '10px')
61968             .style('max-height', '240px')
61969             .style('opacity', '1')
61970             .on('end', function() {
61971                 select(this)
61972                     .style('max-height', '')
61973                     .style('overflow', 'visible');
61974             });
61975
61976
61977         var entry = selection$$1.selectAll('.entry');
61978
61979         utilGetSetValue(entry.select('.localized-lang'), function(d) {
61980                 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
61981                 return lang ? lang[1] : d.lang;
61982             });
61983
61984         utilGetSetValue(entry.select('.localized-value'),
61985             function(d) { return d.value; });
61986     }
61987
61988
61989     localized.tags = function(tags) {
61990         // Fetch translations from wikipedia
61991         if (tags.wikipedia && !wikiTitles) {
61992             wikiTitles = {};
61993             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
61994             if (wm && wm[0] && wm[1]) {
61995                 wikipedia.translations(wm[1], wm[2], function(d) {
61996                     wikiTitles = d;
61997                 });
61998             }
61999         }
62000
62001         utilGetSetValue(input, tags[field.key] || '');
62002
62003         var postfixed = [], k, m;
62004         for (k in tags) {
62005             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
62006             if (m && m[1] === field.key && m[2]) {
62007                 postfixed.push({ lang: m[2], value: tags[k] });
62008             }
62009         }
62010
62011         localizedInputs.call(render, postfixed.reverse());
62012     };
62013
62014
62015     localized.focus = function() {
62016         input.node().focus();
62017     };
62018
62019
62020     localized.entity = function(_) {
62021         if (!arguments.length) return entity;
62022         entity = _;
62023         return localized;
62024     };
62025
62026     return utilRebind(localized, dispatch$$1, 'on');
62027 }
62028
62029 function uiFieldMaxspeed(field, context) {
62030     var dispatch$$1 = dispatch('change'),
62031         entity,
62032         isImperial,
62033         unitInput = select(null),
62034         input = select(null),
62035         combobox;
62036
62037     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
62038         imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
62039
62040
62041     function maxspeed(selection$$1) {
62042         combobox = d3combobox();
62043         var unitCombobox = d3combobox().data(['km/h', 'mph'].map(comboValues));
62044
62045         input = selection$$1.selectAll('#preset-input-' + field.id)
62046             .data([0]);
62047
62048         input = input.enter()
62049             .append('input')
62050             .attr('type', 'text')
62051             .attr('id', 'preset-input-' + field.id)
62052             .attr('placeholder', field.placeholder())
62053             .call(combobox)
62054             .merge(input);
62055
62056         input
62057             .on('change', change)
62058             .on('blur', change);
62059
62060         var childNodes = context.graph().childNodes(context.entity(entity.id)),
62061             loc = childNodes[~~(childNodes.length/2)].loc;
62062
62063         isImperial = lodash.some(dataImperial.features, function(f) {
62064             return lodash.some(f.geometry.coordinates, function(d) {
62065                 return geoPointInPolygon(loc, d);
62066             });
62067         });
62068
62069         unitInput = selection$$1.selectAll('input.maxspeed-unit')
62070             .data([0]);
62071
62072         unitInput = unitInput.enter()
62073             .append('input')
62074             .attr('type', 'text')
62075             .attr('class', 'maxspeed-unit')
62076             .call(unitCombobox)
62077             .merge(unitInput);
62078
62079         unitInput
62080             .on('blur', changeUnits)
62081             .on('change', changeUnits);
62082
62083
62084         function changeUnits() {
62085             isImperial = utilGetSetValue(unitInput) === 'mph';
62086             utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
62087             setSuggestions();
62088             change();
62089         }
62090     }
62091
62092
62093     function setSuggestions() {
62094         combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
62095         utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
62096     }
62097
62098
62099     function comboValues(d) {
62100         return {
62101             value: d.toString(),
62102             title: d.toString()
62103         };
62104     }
62105
62106
62107     function change() {
62108         var tag = {},
62109             value = utilGetSetValue(input);
62110
62111         if (!value) {
62112             tag[field.key] = undefined;
62113         } else if (isNaN(value) || !isImperial) {
62114             tag[field.key] = value;
62115         } else {
62116             tag[field.key] = value + ' mph';
62117         }
62118
62119         dispatch$$1.call('change', this, tag);
62120     }
62121
62122
62123     maxspeed.tags = function(tags) {
62124         var value = tags[field.key];
62125
62126         if (value && value.indexOf('mph') >= 0) {
62127             value = parseInt(value, 10);
62128             isImperial = true;
62129         } else if (value) {
62130             isImperial = false;
62131         }
62132
62133         setSuggestions();
62134         utilGetSetValue(input, value || '');
62135     };
62136
62137
62138     maxspeed.focus = function() {
62139         input.node().focus();
62140     };
62141
62142
62143     maxspeed.entity = function(_) {
62144         entity = _;
62145     };
62146
62147
62148     return utilRebind(maxspeed, dispatch$$1, 'on');
62149 }
62150
62151 function uiFieldRadio(field) {
62152     var dispatch$$1 = dispatch('change'),
62153         placeholder = select(null),
62154         labels = select(null),
62155         radios = select(null);
62156
62157
62158     function radio(selection$$1) {
62159         selection$$1.classed('preset-radio', true);
62160
62161         var wrap = selection$$1.selectAll('.preset-input-wrap')
62162             .data([0]);
62163
62164         var enter = wrap.enter()
62165             .append('div')
62166             .attr('class', 'preset-input-wrap toggle-list');
62167
62168         enter
62169             .append('span')
62170             .attr('class', 'placeholder');
62171
62172         wrap = wrap
62173             .merge(enter);
62174
62175
62176         placeholder = wrap.selectAll('.placeholder');
62177
62178         labels = wrap.selectAll('label')
62179             .data(field.options || field.keys);
62180
62181         enter = labels.enter()
62182             .append('label');
62183
62184         enter.append('input')
62185             .attr('type', 'radio')
62186             .attr('name', field.id)
62187             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
62188             .attr('checked', false);
62189
62190         enter.append('span')
62191             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
62192
62193         labels = labels
62194             .merge(enter);
62195
62196         radios = labels.selectAll('input')
62197             .on('change', change);
62198     }
62199
62200
62201     function change() {
62202         var t$$1 = {};
62203         if (field.key) t$$1[field.key] = undefined;
62204         radios.each(function(d) {
62205             var active$$1 = select(this).property('checked');
62206             if (field.key) {
62207                 if (active$$1) t$$1[field.key] = d;
62208             } else {
62209                 t$$1[d] = active$$1 ? 'yes' : undefined;
62210             }
62211         });
62212         dispatch$$1.call('change', this, t$$1);
62213     }
62214
62215
62216     radio.tags = function(tags) {
62217         function checked(d) {
62218             if (field.key) {
62219                 return tags[field.key] === d;
62220             } else {
62221                 return !!(tags[d] && tags[d] !== 'no');
62222             }
62223         }
62224
62225         labels.classed('active', checked);
62226         radios.property('checked', checked);
62227         var selection$$1 = radios.filter(function() { return this.checked; });
62228         if (selection$$1.empty()) {
62229             placeholder.text(t('inspector.none'));
62230         } else {
62231             placeholder.text(selection$$1.attr('value'));
62232         }
62233     };
62234
62235
62236     radio.focus = function() {
62237         radios.node().focus();
62238     };
62239
62240
62241     return utilRebind(radio, dispatch$$1, 'on');
62242 }
62243
62244 function uiFieldRestrictions(field, context) {
62245     var dispatch$$1 = dispatch('change'),
62246         breathe = behaviorBreathe(context),
62247         hover = behaviorHover(context),
62248         initialized = false,
62249         vertexID,
62250         fromNodeID;
62251
62252
62253     function restrictions(selection$$1) {
62254         // if form field is hidden or has detached from dom, clean up.
62255         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
62256             selection$$1.call(restrictions.off);
62257             return;
62258         }
62259
62260         var wrap = selection$$1.selectAll('.preset-input-wrap')
62261             .data([0]);
62262
62263         var enter = wrap.enter()
62264             .append('div')
62265             .attr('class', 'preset-input-wrap');
62266
62267         enter
62268             .append('div')
62269             .attr('class', 'restriction-help');
62270
62271
62272         var intersection = osmIntersection(context.graph(), vertexID),
62273             graph = intersection.graph,
62274             vertex = graph.entity(vertexID),
62275             filter = utilFunctor(true),
62276             extent$$1 = geoExtent$$1(),
62277             projection = geoRawMercator();
62278
62279         var d = utilGetDimensions(wrap.merge(enter)),
62280             c = [d[0] / 2, d[1] / 2],
62281             z = 24;
62282
62283         projection
62284             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
62285
62286         var s = projection(vertex.loc);
62287
62288         projection
62289             .translate([c[0] - s[0], c[1] - s[1]])
62290             .clipExtent([[0, 0], d]);
62291
62292         var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
62293             drawVertices = svgVertices$$1(projection, context),
62294             drawLines = svgLines$$1(projection, context),
62295             drawTurns = svgTurns(projection, context);
62296
62297         enter
62298             .call(drawLayers);
62299
62300         wrap = wrap
62301             .merge(enter);
62302
62303         var surface = wrap.selectAll('.surface');
62304
62305         if (!enter.empty()) {
62306             initialized = true;
62307             surface
62308                 .call(breathe)
62309                 .call(hover);
62310         }
62311
62312         surface
62313             .call(utilSetDimensions, d)
62314             .call(drawVertices, graph, [vertex], filter, extent$$1, z)
62315             .call(drawLines, graph, intersection.ways, filter)
62316             .call(drawTurns, graph, intersection.turns(fromNodeID));
62317
62318         surface
62319             .on('click.restrictions', click)
62320             .on('mouseover.restrictions', mouseover)
62321             .on('mouseout.restrictions', mouseout);
62322
62323         surface
62324             .selectAll('.selected')
62325             .classed('selected', false);
62326
62327         if (fromNodeID) {
62328             surface
62329                 .selectAll('.' + intersection.highways[fromNodeID].id)
62330                 .classed('selected', true);
62331         }
62332
62333         mouseout();
62334
62335         context.history()
62336             .on('change.restrictions', render);
62337
62338         select(window)
62339             .on('resize.restrictions', function() {
62340                 utilSetDimensions(wrap, null);
62341                 render();
62342             });
62343
62344
62345         function click() {
62346             surface
62347                 .call(breathe.off)
62348                 .call(breathe);
62349
62350             var datum = event.target.__data__;
62351             if (datum instanceof osmEntity$$1) {
62352                 fromNodeID = intersection.adjacentNodeId(datum.id);
62353                 render();
62354             } else if (datum instanceof osmTurn) {
62355                 if (datum.restriction) {
62356                     context.perform(
62357                         actionUnrestrictTurn(datum, projection),
62358                         t('operations.restriction.annotation.delete')
62359                     );
62360                 } else {
62361                     context.perform(
62362                         actionRestrictTurn(datum, projection),
62363                         t('operations.restriction.annotation.create')
62364                     );
62365                 }
62366             }
62367         }
62368
62369
62370         function mouseover() {
62371             var datum = event.target.__data__;
62372             if (datum instanceof osmTurn) {
62373                 var graph = context.graph(),
62374                     presets = context.presets(),
62375                     preset;
62376
62377                 if (datum.restriction) {
62378                     preset = presets.match(graph.entity(datum.restriction), graph);
62379                 } else {
62380                     preset = presets.item('type/restriction/' +
62381                         osmInferRestriction(
62382                             graph,
62383                             datum.from,
62384                             datum.via,
62385                             datum.to,
62386                             projection
62387                         )
62388                     );
62389                 }
62390
62391                 wrap.selectAll('.restriction-help')
62392                     .text(t('operations.restriction.help.' +
62393                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
62394                         { restriction: preset.name() })
62395                     );
62396             }
62397         }
62398
62399
62400         function mouseout() {
62401             wrap.selectAll('.restriction-help')
62402                 .text(t('operations.restriction.help.' +
62403                     (fromNodeID ? 'toggle' : 'select'))
62404                 );
62405         }
62406
62407
62408         function render() {
62409             if (context.hasEntity(vertexID)) {
62410                 restrictions(selection$$1);
62411             }
62412         }
62413     }
62414
62415
62416     restrictions.entity = function(_) {
62417         if (!vertexID || vertexID !== _.id) {
62418             fromNodeID = null;
62419             vertexID = _.id;
62420         }
62421     };
62422
62423
62424     restrictions.tags = function() {};
62425     restrictions.focus = function() {};
62426
62427
62428     restrictions.off = function(selection$$1) {
62429         if (!initialized) return;
62430
62431         selection$$1.selectAll('.surface')
62432             .call(hover.off)
62433             .call(breathe.off)
62434             .on('click.restrictions', null)
62435             .on('mouseover.restrictions', null)
62436             .on('mouseout.restrictions', null);
62437
62438         context.history()
62439             .on('change.restrictions', null);
62440
62441         select(window)
62442             .on('resize.restrictions', null);
62443     };
62444
62445
62446     return utilRebind(restrictions, dispatch$$1, 'on');
62447 }
62448
62449 function uiFieldTextarea(field) {
62450     var dispatch$$1 = dispatch('change'),
62451         input = select(null);
62452
62453
62454     function textarea(selection$$1) {
62455         input = selection$$1.selectAll('textarea')
62456             .data([0]);
62457
62458         input = input.enter()
62459             .append('textarea')
62460             .attr('id', 'preset-input-' + field.id)
62461             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
62462             .attr('maxlength', 255)
62463             .on('input', change(true))
62464             .on('blur', change())
62465             .on('change', change())
62466             .merge(input);
62467     }
62468
62469
62470     function change(onInput) {
62471         return function() {
62472             var t$$1 = {};
62473             t$$1[field.key] = utilGetSetValue(input) || undefined;
62474             dispatch$$1.call('change', this, t$$1, onInput);
62475         };
62476     }
62477
62478
62479     textarea.tags = function(tags) {
62480         utilGetSetValue(input, tags[field.key] || '');
62481     };
62482
62483
62484     textarea.focus = function() {
62485         input.node().focus();
62486     };
62487
62488
62489     return utilRebind(textarea, dispatch$$1, 'on');
62490 }
62491
62492 function uiFieldWikipedia(field, context) {
62493     var dispatch$$1 = dispatch('change'),
62494         wikipedia = services.wikipedia,
62495         wikidata = services.wikidata,
62496         link = select(null),
62497         lang = select(null),
62498         title = select(null),
62499         entity;
62500
62501
62502     function wiki(selection$$1) {
62503         var langcombo = d3combobox()
62504             .fetcher(function(value, cb) {
62505                 var v = value.toLowerCase();
62506
62507                 cb(dataWikipedia.filter(function(d) {
62508                     return d[0].toLowerCase().indexOf(v) >= 0 ||
62509                         d[1].toLowerCase().indexOf(v) >= 0 ||
62510                         d[2].toLowerCase().indexOf(v) >= 0;
62511                 }).map(function(d) {
62512                     return { value: d[1] };
62513                 }));
62514             });
62515
62516         var titlecombo = d3combobox()
62517             .fetcher(function(value, cb) {
62518                 if (!value) {
62519                     value = context.entity(entity.id).tags.name || '';
62520                 }
62521
62522                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
62523                 searchfn(language()[2], value, function(query, data$$1) {
62524                     cb(data$$1.map(function(d) {
62525                         return { value: d };
62526                     }));
62527                 });
62528             });
62529
62530
62531         lang = selection$$1.selectAll('input.wiki-lang')
62532             .data([0]);
62533
62534         lang = lang.enter()
62535             .append('input')
62536             .attr('type', 'text')
62537             .attr('class', 'wiki-lang')
62538             .attr('placeholder', t('translate.localized_translation_language'))
62539             .merge(lang);
62540
62541         utilGetSetValue(lang, language()[1]);
62542
62543         lang
62544             .call(langcombo)
62545             .on('blur', changeLang)
62546             .on('change', changeLang);
62547
62548
62549         title = selection$$1.selectAll('input.wiki-title')
62550             .data([0]);
62551
62552         title = title.enter()
62553             .append('input')
62554             .attr('type', 'text')
62555             .attr('class', 'wiki-title')
62556             .attr('id', 'preset-input-' + field.id)
62557             .merge(title);
62558
62559         title
62560             .call(titlecombo)
62561             .on('blur', blur)
62562             .on('change', change);
62563
62564
62565         link = selection$$1.selectAll('a.wiki-link')
62566             .data([0]);
62567
62568         link = link.enter()
62569             .append('a')
62570             .attr('class', 'wiki-link button-input-action minor')
62571             .attr('tabindex', -1)
62572             .attr('target', '_blank')
62573             .call(svgIcon('#icon-out-link', 'inline'))
62574             .merge(link);
62575     }
62576
62577
62578     function language() {
62579         var value = utilGetSetValue(lang).toLowerCase();
62580         var locale = utilDetect().locale.toLowerCase();
62581         var localeLanguage;
62582         return lodash.find(dataWikipedia, function(d) {
62583             if (d[2] === locale) localeLanguage = d;
62584             return d[0].toLowerCase() === value ||
62585                 d[1].toLowerCase() === value ||
62586                 d[2] === value;
62587         }) || localeLanguage || ['English', 'English', 'en'];
62588     }
62589
62590
62591     function changeLang() {
62592         utilGetSetValue(lang, language()[1]);
62593         change(true);
62594     }
62595
62596
62597     function blur() {
62598         change(true);
62599     }
62600
62601
62602     function change(skipWikidata) {
62603         var value = utilGetSetValue(title),
62604             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
62605             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
62606             anchor,
62607             syncTags = {};
62608
62609         if (l) {
62610             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
62611             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
62612             if (m[3]) {
62613                 try {
62614                     // Best-effort `anchordecode:` implementation
62615                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
62616                 } catch (e) {
62617                     anchor = decodeURIComponent(m[3]);
62618                 }
62619                 value += '#' + anchor.replace(/_/g, ' ');
62620             }
62621             value = value.slice(0, 1).toUpperCase() + value.slice(1);
62622             utilGetSetValue(lang, l[1]);
62623             utilGetSetValue(title, value);
62624         }
62625
62626         syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
62627         if (!skipWikidata) {
62628             syncTags.wikidata = undefined;
62629         }
62630
62631         dispatch$$1.call('change', this, syncTags);
62632
62633
62634         if (skipWikidata || !value || !language()[2]) return;
62635
62636         // attempt asynchronous update of wikidata tag..
62637         var initEntityId = entity.id,
62638             initWikipedia = context.entity(initEntityId).tags.wikipedia;
62639
62640         wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
62641             if (!data$$1 || !Object.keys(data$$1).length) return;
62642             var qids = Object.keys(data$$1);
62643
62644             // 1. most recent change was a tag change
62645             var annotation = t('operations.change_tags.annotation'),
62646                 currAnnotation = context.history().undoAnnotation();
62647             if (currAnnotation !== annotation) return;
62648
62649             // 2. same entity exists and still selected
62650             var selectedIds = context.selectedIDs(),
62651                 currEntityId = selectedIds.length > 0 && selectedIds[0];
62652             if (currEntityId !== initEntityId) return;
62653
62654             // 3. wikipedia value has not changed
62655             var currTags = lodash.clone(context.entity(currEntityId).tags);
62656             if (initWikipedia !== currTags.wikipedia) return;
62657
62658             // ok to coalesce the update of wikidata tag into the previous tag change
62659             currTags.wikidata = qids && lodash.find(qids, function(id) {
62660                 return id.match(/^Q\d+$/);
62661             });
62662
62663             context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
62664             dispatch$$1.call('change', this, currTags);
62665         });
62666     }
62667
62668
62669     wiki.tags = function(tags) {
62670         var value = tags[field.key] || '',
62671             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
62672             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
62673             anchor = m && m[3];
62674
62675         // value in correct format
62676         if (l) {
62677             utilGetSetValue(lang, l[1]);
62678             utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
62679             if (anchor) {
62680                 try {
62681                     // Best-effort `anchorencode:` implementation
62682                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
62683                 } catch (e) {
62684                     anchor = anchor.replace(/ /g, '_');
62685                 }
62686             }
62687             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
62688                 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
62689
62690         // unrecognized value format
62691         } else {
62692             utilGetSetValue(title, value);
62693             if (value && value !== '') {
62694                 utilGetSetValue(lang, '');
62695             }
62696             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
62697         }
62698     };
62699
62700
62701     wiki.entity = function(_) {
62702         if (!arguments.length) return entity;
62703         entity = _;
62704         return wiki;
62705     };
62706
62707
62708     wiki.focus = function() {
62709         title.node().focus();
62710     };
62711
62712
62713     return utilRebind(wiki, dispatch$$1, 'on');
62714 }
62715
62716 var uiFields = {
62717     access: uiFieldAccess,
62718     address: uiFieldAddress,
62719     check: uiFieldCheck,
62720     defaultcheck: uiFieldCheck,
62721     combo: uiFieldCombo,
62722     typeCombo: uiFieldCombo,
62723     multiCombo: uiFieldCombo,
62724     networkCombo: uiFieldCombo,
62725     cycleway: uiFieldCycleway,
62726     text: uiFieldText,
62727     url: uiFieldText,
62728     number: uiFieldText,
62729     email: uiFieldText,
62730     tel: uiFieldText,
62731     localized: uiFieldLocalized,
62732     lanes: uiFieldLanes,
62733     maxspeed: uiFieldMaxspeed,
62734     radio: uiFieldRadio,
62735     restrictions: uiFieldRestrictions,
62736     textarea: uiFieldTextarea,
62737     wikipedia: uiFieldWikipedia
62738 };
62739
62740 function uiPreset(context) {
62741     var dispatch$$1 = dispatch('change'),
62742         state,
62743         fieldsArr,
62744         preset,
62745         tags,
62746         id;
62747
62748
62749     // Field Constructor
62750     function UIField(field, entity, show) {
62751         field = lodash.clone(field);
62752
62753         field.input = uiFields[field.type](field, context)
62754             .on('change', function(t$$1, onInput) {
62755                 dispatch$$1.call('change', field, t$$1, onInput);
62756             });
62757
62758         if (field.input.entity) field.input.entity(entity);
62759
62760         field.keys = field.keys || [field.key];
62761
62762         field.show = show;
62763
62764         field.shown = function() {
62765             return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
62766         };
62767
62768         field.modified = function() {
62769             var original = context.graph().base().entities[entity.id];
62770             return lodash.some(field.keys, function(key) {
62771                 return original ? tags[key] !== original.tags[key] : tags[key];
62772             });
62773         };
62774
62775         field.revert = function() {
62776             var original = context.graph().base().entities[entity.id],
62777                 t$$1 = {};
62778             field.keys.forEach(function(key) {
62779                 t$$1[key] = original ? original.tags[key] : undefined;
62780             });
62781             return t$$1;
62782         };
62783
62784         field.present = function() {
62785             return lodash.some(field.keys, function(key) {
62786                 return tags[key];
62787             });
62788         };
62789
62790         field.remove = function() {
62791             var t$$1 = {};
62792             field.keys.forEach(function(key) {
62793                 t$$1[key] = undefined;
62794             });
62795             return t$$1;
62796         };
62797
62798         return field;
62799     }
62800
62801
62802     function fieldKey(field) {
62803         return field.id;
62804     }
62805
62806
62807     function presets(selection$$1) {
62808         selection$$1.call(uiDisclosure()
62809             .title(t('inspector.all_fields'))
62810             .expanded(context.storage('preset_fields.expanded') !== 'false')
62811             .on('toggled', toggled)
62812             .content(content)
62813         );
62814
62815         function toggled(expanded) {
62816             context.storage('preset_fields.expanded', expanded);
62817         }
62818     }
62819
62820
62821     function content(selection$$1) {
62822         if (!fieldsArr) {
62823             var entity = context.entity(id),
62824                 geometry = context.geometry(id),
62825                 presets = context.presets();
62826
62827             fieldsArr = [];
62828
62829             if (presets.field('name')) {
62830                 fieldsArr.push(UIField(presets.field('name'), entity));
62831             }
62832
62833             preset.fields.forEach(function(field) {
62834                 if (field.matchGeometry(geometry)) {
62835                     fieldsArr.push(UIField(field, entity, true));
62836                 }
62837             });
62838
62839             if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
62840                 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
62841             }
62842
62843             presets.universal().forEach(function(field) {
62844                 if (preset.fields.indexOf(field) < 0) {
62845                     fieldsArr.push(UIField(field, entity));
62846                 }
62847             });
62848         }
62849
62850         var shown = fieldsArr.filter(function(field) { return field.shown(); }),
62851             notShown = fieldsArr.filter(function(field) { return !field.shown(); });
62852
62853
62854         var form = selection$$1.selectAll('.preset-form')
62855             .data([0]);
62856
62857         form = form.enter()
62858             .append('div')
62859             .attr('class', 'preset-form inspector-inner fillL3')
62860             .merge(form);
62861
62862
62863         var fields = form.selectAll('.form-field')
62864             .data(shown, fieldKey);
62865
62866         fields.exit()
62867             .remove();
62868
62869         // Enter
62870         var enter = fields.enter()
62871             .append('div')
62872             .attr('class', function(field) {
62873                 return 'form-field form-field-' + field.id;
62874             });
62875
62876         var label = enter
62877             .append('label')
62878             .attr('class', 'form-label')
62879             .attr('for', function(field) { return 'preset-input-' + field.id; })
62880             .text(function(field) { return field.label(); });
62881
62882         var wrap = label
62883             .append('div')
62884             .attr('class', 'form-label-button-wrap');
62885
62886         wrap.append('button')
62887             .attr('class', 'remove-icon')
62888             .attr('tabindex', -1)
62889             .call(svgIcon('#operation-delete'));
62890
62891         wrap.append('button')
62892             .attr('class', 'modified-icon')
62893             .attr('tabindex', -1)
62894             .call(
62895                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
62896             );
62897
62898
62899         // Update
62900         fields = fields
62901             .merge(enter);
62902
62903         fields.selectAll('.form-label-button-wrap .remove-icon')
62904             .on('click', remove);
62905
62906         fields.selectAll('.modified-icon')
62907             .on('click', revert);
62908
62909         fields
62910             .order()
62911             .classed('modified', function(field) { return field.modified(); })
62912             .classed('present', function(field) { return field.present(); })
62913             .each(function(field) {
62914                 var reference = uiTagReference(field.reference || { key: field.key }, context);
62915
62916                 if (state === 'hover') {
62917                     reference.showing(false);
62918                 }
62919
62920                 select(this)
62921                     .call(field.input)
62922                     .selectAll('input')
62923                     .on('keydown', function() {
62924                         // if user presses enter, and combobox is not active, accept edits..
62925                         if (event.keyCode === 13 && select('.combobox').empty()) {
62926                             context.enter(modeBrowse$$1(context));
62927                         }
62928                     })
62929                     .call(reference.body)
62930                     .select('.form-label-button-wrap')
62931                     .call(reference.button);
62932
62933                 field.input.tags(tags);
62934             });
62935
62936         notShown = notShown.map(function(field) {
62937             return {
62938                 title: field.label(),
62939                 value: field.label(),
62940                 field: field
62941             };
62942         });
62943
62944
62945         var more = selection$$1.selectAll('.more-fields')
62946             .data((notShown.length > 0) ? [0] : []);
62947
62948         more.exit()
62949             .remove();
62950
62951         more = more.enter()
62952             .append('div')
62953             .attr('class', 'more-fields')
62954             .append('label')
62955             .text(t('inspector.add_fields'))
62956             .merge(more);
62957
62958
62959         var input = more.selectAll('.value')
62960             .data([0]);
62961
62962         input.exit()
62963             .remove();
62964
62965         input = input.enter()
62966             .append('input')
62967             .attr('class', 'value')
62968             .attr('type', 'text')
62969             .merge(input);
62970
62971         input
62972             .call(utilGetSetValue, '')
62973             .attr('placeholder', function() {
62974                 var placeholder = [];
62975                 for (var field in notShown) {
62976                     placeholder.push(notShown[field].title);
62977                 }
62978                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
62979             })
62980             .call(d3combobox().data(notShown)
62981                 .minItems(1)
62982                 .on('accept', show));
62983
62984
62985         function show(field) {
62986             field = field.field;
62987             field.show = true;
62988             content(selection$$1);
62989             field.input.focus();
62990         }
62991
62992
62993         function revert(field) {
62994             event.stopPropagation();
62995             event.preventDefault();
62996             dispatch$$1.call('change', field, field.revert());
62997         }
62998
62999
63000         function remove(field) {
63001             event.stopPropagation();
63002             event.preventDefault();
63003             dispatch$$1.call('change', field, field.remove());
63004         }
63005     }
63006
63007
63008     presets.preset = function(_) {
63009         if (!arguments.length) return preset;
63010         if (preset && preset.id === _.id) return presets;
63011         preset = _;
63012         fieldsArr = null;
63013         return presets;
63014     };
63015
63016
63017     presets.state = function(_) {
63018         if (!arguments.length) return state;
63019         state = _;
63020         return presets;
63021     };
63022
63023
63024     presets.tags = function(_) {
63025         if (!arguments.length) return tags;
63026         tags = _;
63027         // Don't reset fieldsArr here.
63028         return presets;
63029     };
63030
63031
63032     presets.entityID = function(_) {
63033         if (!arguments.length) return id;
63034         if (id === _) return presets;
63035         id = _;
63036         fieldsArr = null;
63037         return presets;
63038     };
63039
63040
63041     return utilRebind(presets, dispatch$$1, 'on');
63042 }
63043
63044 function uiEntityEditor(context) {
63045     var dispatch$$1 = dispatch('choose'),
63046         state = 'select',
63047         coalesceChanges = false,
63048         modified = false,
63049         base,
63050         id,
63051         activePreset,
63052         reference;
63053
63054     var presetEditor = uiPreset(context)
63055         .on('change', changeTags);
63056     var rawTagEditor = uiRawTagEditor(context)
63057         .on('change', changeTags);
63058
63059
63060     function entityEditor(selection$$1) {
63061         var entity = context.entity(id),
63062             tags = lodash.clone(entity.tags);
63063
63064         // Header
63065         var header = selection$$1.selectAll('.header')
63066             .data([0]);
63067
63068         // Enter
63069         var enter = header.enter()
63070             .append('div')
63071             .attr('class', 'header fillL cf');
63072
63073         enter
63074             .append('button')
63075             .attr('class', 'fl preset-reset preset-choose')
63076             .append('span')
63077             .html((textDirection === 'rtl') ? '&#9658;' : '&#9668;');
63078
63079         enter
63080             .append('button')
63081             .attr('class', 'fr preset-close')
63082             .on('click', function() { context.enter(modeBrowse$$1(context)); })
63083             .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
63084
63085         enter
63086             .append('h3')
63087             .text(t('inspector.edit'));
63088
63089         // Update
63090         header = header
63091             .merge(enter);
63092
63093         header.selectAll('.preset-reset')
63094             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
63095
63096
63097         // Body
63098         var body = selection$$1.selectAll('.inspector-body')
63099             .data([0]);
63100
63101         // Enter
63102         enter = body.enter()
63103             .append('div')
63104             .attr('class', 'inspector-body');
63105
63106         enter
63107             .append('div')
63108             .attr('class', 'preset-list-item inspector-inner')
63109             .append('div')
63110             .attr('class', 'preset-list-button-wrap')
63111             .append('button')
63112             .attr('class', 'preset-list-button preset-reset')
63113             .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
63114             .append('div')
63115             .attr('class', 'label');
63116
63117         enter
63118             .append('div')
63119             .attr('class', 'inspector-border inspector-preset');
63120
63121         enter
63122             .append('div')
63123             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
63124
63125         enter
63126             .append('div')
63127             .attr('class', 'inspector-border raw-member-editor inspector-inner');
63128
63129         enter
63130             .append('div')
63131             .attr('class', 'raw-membership-editor inspector-inner');
63132
63133         // Update
63134         body = body
63135             .merge(enter);
63136
63137         body.selectAll('.preset-list-button-wrap')
63138             .call(reference.button);
63139
63140         body.selectAll('.preset-list-item')
63141             .call(reference.body);
63142
63143         body.selectAll('.preset-reset')
63144             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
63145
63146         body.select('.preset-list-item button')
63147             .call(uiPresetIcon()
63148                 .geometry(context.geometry(id))
63149                 .preset(activePreset));
63150
63151         body.select('.preset-list-item .label')
63152             .text(activePreset.name());
63153
63154         body.select('.inspector-preset')
63155             .call(presetEditor
63156                 .preset(activePreset)
63157                 .entityID(id)
63158                 .tags(tags)
63159                 .state(state));
63160
63161         body.select('.raw-tag-editor')
63162             .call(rawTagEditor
63163                 .preset(activePreset)
63164                 .entityID(id)
63165                 .tags(tags)
63166                 .state(state));
63167
63168         if (entity.type === 'relation') {
63169             body.select('.raw-member-editor')
63170                 .style('display', 'block')
63171                 .call(uiRawMemberEditor(context)
63172                     .entityID(id));
63173         } else {
63174             body.select('.raw-member-editor')
63175                 .style('display', 'none');
63176         }
63177
63178         body.select('.raw-membership-editor')
63179             .call(uiRawMembershipEditor(context)
63180                 .entityID(id));
63181
63182
63183         context.history()
63184             .on('change.entity-editor', historyChanged);
63185
63186
63187         function historyChanged() {
63188             if (state === 'hide') return;
63189
63190             var entity = context.hasEntity(id),
63191                 graph = context.graph();
63192             if (!entity) return;
63193
63194             entityEditor.preset(context.presets().match(entity, graph));
63195             entityEditor.modified(base !== graph);
63196             entityEditor(selection$$1);
63197         }
63198     }
63199
63200
63201     function clean(o) {
63202
63203         function cleanVal(k, v) {
63204             function keepSpaces(k) {
63205                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
63206                     'operating_times', 'smoking_hours', 'happy_hours'];
63207                 return lodash.some(whitelist, function(s) { return k.indexOf(s) !== -1; });
63208             }
63209
63210             var blacklist = ['description', 'note', 'fixme'];
63211             if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
63212
63213             var cleaned = v.split(';')
63214                 .map(function(s) { return s.trim(); })
63215                 .join(keepSpaces(k) ? '; ' : ';');
63216
63217             // The code below is not intended to validate websites and emails.
63218             // It is only intended to prevent obvious copy-paste errors. (#2323)
63219
63220             // clean website- and email-like tags
63221             if (k.indexOf('website') !== -1 ||
63222                 k.indexOf('email') !== -1 ||
63223                 cleaned.indexOf('http') === 0) {
63224                 cleaned = cleaned
63225                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
63226
63227             }
63228
63229             return cleaned;
63230         }
63231
63232         var out = {}, k, v;
63233         for (k in o) {
63234             if (k && (v = o[k]) !== undefined) {
63235                 out[k] = cleanVal(k, v);
63236             }
63237         }
63238         return out;
63239     }
63240
63241
63242     // Tag changes that fire on input can all get coalesced into a single
63243     // history operation when the user leaves the field.  #2342
63244     function changeTags(changed, onInput) {
63245         var entity = context.entity(id),
63246             annotation = t('operations.change_tags.annotation'),
63247             tags = lodash.clone(entity.tags);
63248
63249         lodash.forEach(changed, function(v, k) {
63250             if (v !== undefined || tags.hasOwnProperty(k)) {
63251                 tags[k] = v;
63252             }
63253         });
63254
63255         if (!onInput) {
63256             tags = clean(tags);
63257         }
63258
63259         if (!lodash.isEqual(entity.tags, tags)) {
63260             if (coalesceChanges) {
63261                 context.overwrite(actionChangeTags(id, tags), annotation);
63262             } else {
63263                 context.perform(actionChangeTags(id, tags), annotation);
63264                 coalesceChanges = !!onInput;
63265             }
63266         }
63267     }
63268
63269
63270     entityEditor.modified = function(_) {
63271         if (!arguments.length) return modified;
63272         modified = _;
63273         selectAll('button.preset-close use')
63274             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
63275     };
63276
63277
63278     entityEditor.state = function(_) {
63279         if (!arguments.length) return state;
63280         state = _;
63281         return entityEditor;
63282     };
63283
63284
63285     entityEditor.entityID = function(_) {
63286         if (!arguments.length) return id;
63287         id = _;
63288         base = context.graph();
63289         entityEditor.preset(context.presets().match(context.entity(id), base));
63290         entityEditor.modified(false);
63291         coalesceChanges = false;
63292         return entityEditor;
63293     };
63294
63295
63296     entityEditor.preset = function(_) {
63297         if (!arguments.length) return activePreset;
63298         if (_ !== activePreset) {
63299             activePreset = _;
63300             reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
63301                 .showing(false);
63302         }
63303         return entityEditor;
63304     };
63305
63306
63307     return utilRebind(entityEditor, dispatch$$1, 'on');
63308 }
63309
63310 function uiPresetList(context) {
63311     var dispatch$$1 = dispatch('choose'),
63312         id,
63313         currentPreset,
63314         autofocus = false;
63315
63316
63317     function presetList(selection$$1) {
63318         var entity = context.entity(id),
63319             geometry = context.geometry(id);
63320
63321         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
63322         if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
63323             geometry = 'point';
63324         }
63325
63326         var presets = context.presets().matchGeometry(geometry);
63327
63328         selection$$1.html('');
63329
63330         var messagewrap = selection$$1
63331             .append('div')
63332             .attr('class', 'header fillL cf');
63333
63334         var message = messagewrap
63335             .append('h3')
63336             .text(t('inspector.choose'));
63337
63338         if (context.entity(id).isUsed(context.graph())) {
63339             messagewrap
63340                 .append('button')
63341                 .attr('class', 'preset-choose')
63342                 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
63343                 .append('span')
63344                 .html((textDirection === 'rtl') ? '&#9668;' : '&#9658;');
63345         } else {
63346             messagewrap
63347                 .append('button')
63348                 .attr('class', 'close')
63349                 .on('click', function() {
63350                     context.enter(modeBrowse$$1(context));
63351                 })
63352                 .call(svgIcon('#icon-close'));
63353         }
63354
63355         function keydown() {
63356             // hack to let delete shortcut work when search is autofocused
63357             if (search.property('value').length === 0 &&
63358                 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
63359                  event.keyCode === d3keybinding.keyCodes['⌦'])) {
63360                 event.preventDefault();
63361                 event.stopPropagation();
63362                 operationDelete([id], context)();
63363             } else if (search.property('value').length === 0 &&
63364                 (event.ctrlKey || event.metaKey) &&
63365                 event.keyCode === d3keybinding.keyCodes.z) {
63366                 event.preventDefault();
63367                 event.stopPropagation();
63368                 context.undo();
63369             } else if (!event.ctrlKey && !event.metaKey) {
63370                 select(this).on('keydown', null);
63371             }
63372         }
63373
63374         function keypress() {
63375             // enter
63376             var value = search.property('value');
63377             if (event.keyCode === 13 && value.length) {
63378                 list.selectAll('.preset-list-item:first-child').datum().choose();
63379             }
63380         }
63381
63382         function inputevent() {
63383             var value = search.property('value');
63384             list.classed('filtered', value.length);
63385             if (value.length) {
63386                 var results = presets.search(value, geometry);
63387                 message.text(t('inspector.results', {
63388                     n: results.collection.length,
63389                     search: value
63390                 }));
63391                 list.call(drawList, results);
63392             } else {
63393                 list.call(drawList, context.presets().defaults(geometry, 36));
63394                 message.text(t('inspector.choose'));
63395             }
63396         }
63397
63398         var searchWrap = selection$$1
63399             .append('div')
63400             .attr('class', 'search-header');
63401
63402         var search = searchWrap
63403             .append('input')
63404             .attr('class', 'preset-search-input')
63405             .attr('placeholder', t('inspector.search'))
63406             .attr('type', 'search')
63407             .on('keydown', keydown)
63408             .on('keypress', keypress)
63409             .on('input', inputevent);
63410
63411         searchWrap
63412             .call(svgIcon('#icon-search', 'pre-text'));
63413
63414         if (autofocus) {
63415             search.node().focus();
63416         }
63417
63418         var listWrap = selection$$1
63419             .append('div')
63420             .attr('class', 'inspector-body');
63421
63422         var list = listWrap
63423             .append('div')
63424             .attr('class', 'preset-list fillL cf')
63425             .call(drawList, context.presets().defaults(geometry, 36));
63426     }
63427
63428
63429     function drawList(list, presets) {
63430         var collection = presets.collection.map(function(preset) {
63431             return preset.members ? CategoryItem(preset) : PresetItem(preset);
63432         });
63433
63434         var items = list.selectAll('.preset-list-item')
63435             .data(collection, function(d) { return d.preset.id; });
63436
63437         items.order();
63438
63439         items.exit()
63440             .remove();
63441
63442         items.enter()
63443             .append('div')
63444             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
63445             .classed('current', function(item) { return item.preset === currentPreset; })
63446             .each(function(item) { select(this).call(item); })
63447             .style('opacity', 0)
63448             .transition()
63449             .style('opacity', 1);
63450     }
63451
63452
63453     function CategoryItem(preset) {
63454         var box, sublist, shown = false;
63455
63456         function item(selection$$1) {
63457             var wrap = selection$$1.append('div')
63458                 .attr('class', 'preset-list-button-wrap category col12');
63459
63460             wrap.append('button')
63461                 .attr('class', 'preset-list-button')
63462                 .classed('expanded', false)
63463                 .call(uiPresetIcon()
63464                     .geometry(context.geometry(id))
63465                     .preset(preset))
63466                 .on('click', function() {
63467                     var isExpanded = select(this).classed('expanded');
63468                     var triangle = isExpanded ? '▶ ' :  '▼ ';
63469                     select(this).classed('expanded', !isExpanded);
63470                     select(this).selectAll('.label').text(triangle + preset.name());
63471                     item.choose();
63472                 })
63473                 .append('div')
63474                 .attr('class', 'label')
63475                 .text(function() {
63476                   return '▶ ' + preset.name();
63477                 });
63478
63479             box = selection$$1.append('div')
63480                 .attr('class', 'subgrid col12')
63481                 .style('max-height', '0px')
63482                 .style('opacity', 0);
63483
63484             box.append('div')
63485                 .attr('class', 'arrow');
63486
63487             sublist = box.append('div')
63488                 .attr('class', 'preset-list fillL3 cf fl');
63489         }
63490
63491         item.choose = function() {
63492             if (!box || !sublist) return;
63493
63494             if (shown) {
63495                 shown = false;
63496                 box.transition()
63497                     .duration(200)
63498                     .style('opacity', '0')
63499                     .style('max-height', '0px')
63500                     .style('padding-bottom', '0px');
63501             } else {
63502                 shown = true;
63503                 sublist.call(drawList, preset.members);
63504                 box.transition()
63505                     .duration(200)
63506                     .style('opacity', '1')
63507                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
63508                     .style('padding-bottom', '20px');
63509             }
63510         };
63511
63512         item.preset = preset;
63513
63514         return item;
63515     }
63516
63517
63518     function PresetItem(preset) {
63519         function item(selection$$1) {
63520             var wrap = selection$$1.append('div')
63521                 .attr('class', 'preset-list-button-wrap col12');
63522
63523             wrap.append('button')
63524                 .attr('class', 'preset-list-button')
63525                 .call(uiPresetIcon()
63526                     .geometry(context.geometry(id))
63527                     .preset(preset))
63528                 .on('click', item.choose)
63529                 .append('div')
63530                 .attr('class', 'label')
63531                 .text(preset.name());
63532
63533             wrap.call(item.reference.button);
63534             selection$$1.call(item.reference.body);
63535         }
63536
63537         item.choose = function() {
63538             context.presets().choose(preset);
63539
63540             context.perform(
63541                 actionChangePreset(id, currentPreset, preset),
63542                 t('operations.change_tags.annotation')
63543             );
63544
63545             dispatch$$1.call('choose', this, preset);
63546         };
63547
63548         item.help = function() {
63549             event.stopPropagation();
63550             item.reference.toggle();
63551         };
63552
63553         item.preset = preset;
63554         item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
63555
63556         return item;
63557     }
63558
63559
63560     presetList.autofocus = function(_) {
63561         if (!arguments.length) return autofocus;
63562         autofocus = _;
63563         return presetList;
63564     };
63565
63566
63567     presetList.entityID = function(_) {
63568         if (!arguments.length) return id;
63569         id = _;
63570         presetList.preset(context.presets().match(context.entity(id), context.graph()));
63571         return presetList;
63572     };
63573
63574
63575     presetList.preset = function(_) {
63576         if (!arguments.length) return currentPreset;
63577         currentPreset = _;
63578         return presetList;
63579     };
63580
63581
63582     return utilRebind(presetList, dispatch$$1, 'on');
63583 }
63584
63585 function uiViewOnOSM(context) {
63586     var id;
63587
63588     function viewOnOSM(selection) {
63589         var entity = context.entity(id);
63590
63591         selection.style('display', entity.isNew() ? 'none' : null);
63592
63593         var link = selection.selectAll('.view-on-osm')
63594             .data([0]);
63595
63596         link.enter()
63597             .append('a')
63598             .attr('class', 'view-on-osm')
63599             .attr('target', '_blank')
63600             .call(svgIcon('#icon-out-link', 'inline'))
63601             .append('span')
63602             .text(t('inspector.view_on_osm'));
63603
63604         link
63605             .attr('href', context.connection().entityURL(entity));
63606     }
63607
63608
63609     viewOnOSM.entityID = function(_) {
63610         if (!arguments.length) return id;
63611         id = _;
63612         return viewOnOSM;
63613     };
63614
63615     return viewOnOSM;
63616 }
63617
63618 function uiInspector(context) {
63619     var presetList = uiPresetList(context),
63620         entityEditor = uiEntityEditor(context),
63621         state = 'select',
63622         entityID,
63623         newFeature = false;
63624
63625
63626     function inspector(selection$$1) {
63627         presetList
63628             .entityID(entityID)
63629             .autofocus(newFeature)
63630             .on('choose', setPreset);
63631
63632         entityEditor
63633             .state(state)
63634             .entityID(entityID)
63635             .on('choose', showList);
63636
63637         var wrap = selection$$1.selectAll('.panewrap')
63638             .data([0]);
63639
63640         var enter = wrap.enter()
63641             .append('div')
63642             .attr('class', 'panewrap');
63643
63644         enter
63645             .append('div')
63646             .attr('class', 'preset-list-pane pane');
63647
63648         enter
63649             .append('div')
63650             .attr('class', 'entity-editor-pane pane');
63651
63652         wrap = wrap.merge(enter);
63653         var presetPane = wrap.selectAll('.preset-list-pane');
63654         var editorPane = wrap.selectAll('.entity-editor-pane');
63655
63656         var graph = context.graph(),
63657             entity = context.entity(entityID),
63658             showEditor = state === 'hover' ||
63659                 entity.isUsed(graph) ||
63660                 entity.isHighwayIntersection(graph);
63661
63662         if (showEditor) {
63663             wrap.style('right', '0%');
63664             editorPane.call(entityEditor);
63665         } else {
63666             wrap.style('right', '-100%');
63667             presetPane.call(presetList);
63668         }
63669
63670         var footer = selection$$1.selectAll('.footer')
63671             .data([0]);
63672
63673         footer = footer.enter()
63674             .append('div')
63675             .attr('class', 'footer')
63676             .merge(footer);
63677
63678         footer
63679             .call(uiViewOnOSM(context).entityID(entityID));
63680
63681
63682         function showList(preset) {
63683             wrap.transition()
63684                 .styleTween('right', function() { return interpolate('0%', '-100%'); });
63685
63686             presetPane
63687                 .call(presetList.preset(preset).autofocus(true));
63688         }
63689
63690
63691         function setPreset(preset) {
63692             wrap.transition()
63693                 .styleTween('right', function() { return interpolate('-100%', '0%'); });
63694
63695             editorPane
63696                 .call(entityEditor.preset(preset));
63697         }
63698     }
63699
63700
63701     inspector.state = function(_) {
63702         if (!arguments.length) return state;
63703         state = _;
63704         entityEditor.state(state);
63705         return inspector;
63706     };
63707
63708
63709     inspector.entityID = function(_) {
63710         if (!arguments.length) return entityID;
63711         entityID = _;
63712         return inspector;
63713     };
63714
63715
63716     inspector.newFeature = function(_) {
63717         if (!arguments.length) return newFeature;
63718         newFeature = _;
63719         return inspector;
63720     };
63721
63722
63723     return inspector;
63724 }
63725
63726 function uiNotice(context) {
63727
63728     return function(selection) {
63729         var div = selection
63730             .append('div')
63731             .attr('class', 'notice');
63732
63733         var button = div
63734             .append('button')
63735             .attr('class', 'zoom-to notice')
63736             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
63737
63738         button
63739             .call(svgIcon('#icon-plus', 'pre-text'))
63740             .append('span')
63741             .attr('class', 'label')
63742             .text(t('zoom_in_edit'));
63743
63744
63745         function disableTooHigh() {
63746             div.style('display', context.editable() ? 'none' : 'block');
63747         }
63748
63749         context.map()
63750             .on('move.notice', lodash.debounce(disableTooHigh, 500));
63751
63752         disableTooHigh();
63753     };
63754 }
63755
63756 function uiSidebar(context) {
63757     var inspector = uiInspector(context),
63758         current;
63759
63760
63761     function sidebar(selection) {
63762         var featureListWrap = selection
63763             .append('div')
63764             .attr('class', 'feature-list-pane')
63765             .call(uiFeatureList(context));
63766
63767         selection
63768             .call(uiNotice(context));
63769
63770         var inspectorWrap = selection
63771             .append('div')
63772             .attr('class', 'inspector-hidden inspector-wrap fr');
63773
63774
63775         function hover(id) {
63776             if (!current && context.hasEntity(id)) {
63777                 featureListWrap
63778                     .classed('inspector-hidden', true);
63779
63780                 inspectorWrap
63781                     .classed('inspector-hidden', false)
63782                     .classed('inspector-hover', true);
63783
63784                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
63785                     inspector
63786                         .state('hover')
63787                         .entityID(id);
63788
63789                     inspectorWrap
63790                         .call(inspector);
63791                 }
63792
63793             } else if (!current) {
63794                 featureListWrap
63795                     .classed('inspector-hidden', false);
63796                 inspectorWrap
63797                     .classed('inspector-hidden', true);
63798                 inspector
63799                     .state('hide');
63800             }
63801         }
63802
63803
63804         sidebar.hover = lodash.throttle(hover, 200);
63805
63806
63807         sidebar.select = function(id, newFeature) {
63808             if (!current && id) {
63809                 featureListWrap
63810                     .classed('inspector-hidden', true);
63811
63812                 inspectorWrap
63813                     .classed('inspector-hidden', false)
63814                     .classed('inspector-hover', false);
63815
63816                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
63817                     inspector
63818                         .state('select')
63819                         .entityID(id)
63820                         .newFeature(newFeature);
63821
63822                     inspectorWrap
63823                         .call(inspector);
63824                 }
63825
63826             } else if (!current) {
63827                 featureListWrap
63828                     .classed('inspector-hidden', false);
63829                 inspectorWrap
63830                     .classed('inspector-hidden', true);
63831                 inspector
63832                     .state('hide');
63833             }
63834         };
63835
63836
63837         sidebar.show = function(component) {
63838             featureListWrap
63839                 .classed('inspector-hidden', true);
63840             inspectorWrap
63841                 .classed('inspector-hidden', true);
63842
63843             if (current) current.remove();
63844             current = selection
63845                 .append('div')
63846                 .attr('class', 'sidebar-component')
63847                 .call(component);
63848         };
63849
63850
63851         sidebar.hide = function() {
63852             featureListWrap
63853                 .classed('inspector-hidden', false);
63854             inspectorWrap
63855                 .classed('inspector-hidden', true);
63856
63857             if (current) current.remove();
63858             current = null;
63859         };
63860     }
63861
63862
63863     sidebar.hover = function() {};
63864     sidebar.hover.cancel = function() {};
63865     sidebar.select = function() {};
63866     sidebar.show = function() {};
63867     sidebar.hide = function() {};
63868
63869     return sidebar;
63870 }
63871
63872 function uiSpinner(context) {
63873     var connection = context.connection();
63874
63875
63876     return function(selection) {
63877         var img = selection
63878             .append('img')
63879             .attr('src', context.imagePath('loader-black.gif'))
63880             .style('opacity', 0);
63881
63882         connection
63883             .on('loading.spinner', function() {
63884                 img.transition()
63885                     .style('opacity', 1);
63886             });
63887
63888         connection
63889             .on('loaded.spinner', function() {
63890                 img.transition()
63891                     .style('opacity', 0);
63892             });
63893     };
63894 }
63895
63896 function uiSplash(context) {
63897
63898     return function(selection$$1) {
63899         if (context.storage('sawSplash'))
63900              return;
63901
63902         context.storage('sawSplash', true);
63903
63904         var modalSelection = uiModal(selection$$1);
63905
63906         modalSelection.select('.modal')
63907             .attr('class', 'modal-splash modal col6');
63908
63909         var introModal = modalSelection.select('.content')
63910             .append('div')
63911             .attr('class', 'fillL');
63912
63913         introModal
63914             .append('div')
63915             .attr('class','modal-section cf')
63916             .append('h3').text(t('splash.welcome'));
63917
63918         introModal
63919             .append('div')
63920             .attr('class','modal-section')
63921             .append('p')
63922             .html(t('splash.text', {
63923                 version: context.version,
63924                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
63925                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
63926             }));
63927
63928         var buttons = introModal
63929             .append('div')
63930             .attr('class', 'modal-actions cf');
63931
63932         buttons
63933             .append('button')
63934             .attr('class', 'col6 walkthrough')
63935             .text(t('splash.walkthrough'))
63936             .on('click', function() {
63937                 select(document.body).call(uiIntro(context));
63938                 modalSelection.close();
63939             });
63940
63941         buttons
63942             .append('button')
63943             .attr('class', 'col6 start')
63944             .text(t('splash.start'))
63945             .on('click', modalSelection.close);
63946
63947         modalSelection.select('button.close')
63948             .attr('class','hide');
63949
63950     };
63951 }
63952
63953 function uiStatus(context) {
63954     var connection = context.connection();
63955
63956     return function(selection$$1) {
63957
63958         function update() {
63959             connection.status(function(err, apiStatus) {
63960                 selection$$1.html('');
63961
63962                 if (err) {
63963                     if (apiStatus === 'rateLimited') {
63964                         selection$$1
63965                             .text(t('status.rateLimit'))
63966                             .append('a')
63967                             .attr('class', 'api-status-login')
63968                             .attr('target', '_blank')
63969                             .call(svgIcon('#icon-out-link', 'inline'))
63970                             .append('span')
63971                             .text(t('login'))
63972                             .on('click.login', function() {
63973                                 event.preventDefault();
63974                                 connection.authenticate();
63975                             });
63976                     } else {
63977                         // TODO: nice messages for different error types
63978                         selection$$1.text(t('status.error'));
63979                     }
63980
63981                 } else if (apiStatus === 'readonly') {
63982                     selection$$1.text(t('status.readonly'));
63983                 } else if (apiStatus === 'offline') {
63984                     selection$$1.text(t('status.offline'));
63985                 }
63986
63987                 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
63988             });
63989         }
63990
63991         connection
63992             .on('change', function() { update(selection$$1); });
63993
63994         window.setInterval(update, 90000);
63995         update(selection$$1);
63996     };
63997 }
63998
63999 function uiUndoRedo(context) {
64000     var commands = [{
64001         id: 'undo',
64002         cmd: uiCmd('⌘Z'),
64003         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
64004         annotation: function() { return context.history().undoAnnotation(); }
64005     }, {
64006         id: 'redo',
64007         cmd: uiCmd('⌘⇧Z'),
64008         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
64009         annotation: function() { return context.history().redoAnnotation(); }
64010     }];
64011
64012
64013     function saving() {
64014         return context.mode().id === 'save';
64015     }
64016
64017
64018     return function(selection$$1) {
64019         var tooltipBehavior = tooltip()
64020             .placement('bottom')
64021             .html(true)
64022             .title(function (d) {
64023                 return uiTooltipHtml(d.annotation() ?
64024                     t(d.id + '.tooltip', {action: d.annotation()}) :
64025                     t(d.id + '.nothing'), d.cmd);
64026             });
64027
64028         var buttons = selection$$1.selectAll('button')
64029             .data(commands)
64030             .enter()
64031             .append('button')
64032             .attr('class', 'col6 disabled')
64033             .on('click', function(d) { return d.action(); })
64034             .call(tooltipBehavior);
64035
64036         buttons.each(function(d) {
64037             var iconName = d.id;
64038             if (textDirection === 'rtl') {
64039                 if (iconName === 'undo') {
64040                     iconName = 'redo';
64041                 } else if (iconName === 'redo') {
64042                     iconName = 'undo';
64043                 }
64044             }
64045             select(this)
64046                 .call(svgIcon('#icon-' + iconName));
64047         });
64048
64049         var keybinding = d3keybinding('undo')
64050             .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
64051             .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
64052
64053         select(document)
64054             .call(keybinding);
64055
64056         context.history()
64057             .on('change.undo_redo', update);
64058
64059         context
64060             .on('enter.undo_redo', update);
64061
64062         function update() {
64063             buttons
64064                 .property('disabled', saving())
64065                 .classed('disabled', function(d) { return !d.annotation(); })
64066                 .each(function() {
64067                     var selection$$1 = select(this);
64068                     if (selection$$1.property('tooltipVisible')) {
64069                         selection$$1.call(tooltipBehavior.show);
64070                     }
64071                 });
64072         }
64073     };
64074 }
64075
64076 function uiZoom(context) {
64077     var zooms = [{
64078         id: 'zoom-in',
64079         icon: 'plus',
64080         title: t('zoom.in'),
64081         action: context.zoomIn,
64082         key: '+'
64083     }, {
64084         id: 'zoom-out',
64085         icon: 'minus',
64086         title: t('zoom.out'),
64087         action: context.zoomOut,
64088         key: '-'
64089     }];
64090
64091
64092     function zoomIn() {
64093         event.preventDefault();
64094         if (!context.inIntro()) context.zoomIn();
64095     }
64096
64097
64098     function zoomOut() {
64099         event.preventDefault();
64100         if (!context.inIntro()) context.zoomOut();
64101     }
64102
64103
64104     function zoomInFurther() {
64105         event.preventDefault();
64106         if (!context.inIntro()) context.zoomInFurther();
64107     }
64108
64109
64110     function zoomOutFurther() {
64111         event.preventDefault();
64112         if (!context.inIntro()) context.zoomOutFurther();
64113     }
64114
64115
64116     return function(selection$$1) {
64117         var button = selection$$1.selectAll('button')
64118             .data(zooms)
64119             .enter()
64120             .append('button')
64121             .attr('tabindex', -1)
64122             .attr('class', function(d) { return d.id; })
64123             .on('click.editor', function(d) { d.action(); })
64124             .call(tooltip()
64125                 .placement((textDirection === 'rtl') ? 'right' : 'left')
64126                 .html(true)
64127                 .title(function(d) {
64128                     return uiTooltipHtml(d.title, d.key);
64129                 })
64130             );
64131
64132         button.each(function(d) {
64133             select(this)
64134                 .call(svgIcon('#icon-' + d.icon, 'light'));
64135         });
64136
64137         var keybinding = d3keybinding('zoom');
64138
64139         lodash.each(['=','ffequals','plus','ffplus'], function(key) {
64140             keybinding.on([key, '⇧' + key], zoomIn);
64141             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
64142         });
64143         lodash.each(['-','ffminus','dash'], function(key) {
64144             keybinding.on([key, '⇧' + key], zoomOut);
64145             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
64146         });
64147
64148         select(document)
64149             .call(keybinding);
64150     };
64151 }
64152
64153 function uiInit(context) {
64154
64155     function render(container) {
64156         var map$$1 = context.map();
64157
64158         var hash = behaviorHash(context);
64159         hash();
64160
64161         if (!hash.hadHash) {
64162             map$$1.centerZoom([0, 0], 2);
64163         }
64164
64165         container
64166             .append('svg')
64167             .attr('id', 'defs')
64168             .call(svgDefs(context));
64169
64170         container
64171             .append('div')
64172             .attr('id', 'sidebar')
64173             .attr('class', 'col4')
64174             .call(ui.sidebar);
64175
64176         var content = container
64177             .append('div')
64178             .attr('id', 'content');
64179
64180         var bar = content
64181             .append('div')
64182             .attr('id', 'bar')
64183             .attr('class', 'fillD');
64184
64185         content
64186             .append('div')
64187             .attr('id', 'map')
64188             .attr('dir', 'ltr')
64189             .call(map$$1);
64190
64191         if (textDirection === 'rtl') {
64192             select('body').attr('dir', 'rtl');
64193         }
64194
64195         content
64196             .call(uiMapInMap(context));
64197
64198         content
64199             .append('div')
64200             .call(uiInfo(context));
64201
64202         bar
64203             .append('div')
64204             .attr('class', 'spacer col4');
64205
64206         var limiter = bar.append('div')
64207             .attr('class', 'limiter');
64208
64209         limiter
64210             .append('div')
64211             .attr('class', 'button-wrap joined col3')
64212             .call(uiModes(context), limiter);
64213
64214         limiter
64215             .append('div')
64216             .attr('class', 'button-wrap joined col1')
64217             .call(uiUndoRedo(context));
64218
64219         limiter
64220             .append('div')
64221             .attr('class', 'button-wrap col1')
64222             .call(uiSave(context));
64223
64224         bar
64225             .append('div')
64226             .attr('class', 'full-screen')
64227             .call(uiFullScreen(context));
64228
64229         bar
64230             .append('div')
64231             .attr('class', 'spinner')
64232             .call(uiSpinner(context));
64233
64234         var controls = bar
64235             .append('div')
64236             .attr('class', 'map-controls');
64237
64238         controls
64239             .append('div')
64240             .attr('class', 'map-control zoombuttons')
64241             .call(uiZoom(context));
64242
64243         controls
64244             .append('div')
64245             .attr('class', 'map-control geolocate-control')
64246             .call(uiGeolocate(context));
64247
64248         controls
64249             .append('div')
64250             .attr('class', 'map-control background-control')
64251             .call(uiBackground(context));
64252
64253         controls
64254             .append('div')
64255             .attr('class', 'map-control map-data-control')
64256             .call(uiMapData(context));
64257
64258         controls
64259             .append('div')
64260             .attr('class', 'map-control help-control')
64261             .call(uiHelp(context));
64262
64263         var about = content
64264             .append('div')
64265             .attr('id', 'about');
64266
64267         about
64268             .append('div')
64269             .attr('id', 'attrib')
64270             .attr('dir', 'ltr')
64271             .call(uiAttribution(context));
64272
64273         var footer = about
64274             .append('div')
64275             .attr('id', 'footer')
64276             .attr('class', 'fillD');
64277
64278         footer
64279             .append('div')
64280             .attr('class', 'api-status')
64281             .call(uiStatus(context));
64282
64283         footer
64284             .append('div')
64285             .attr('id', 'scale-block')
64286             .call(uiScale(context));
64287
64288         var aboutList = footer
64289             .append('div')
64290             .attr('id', 'info-block')
64291             .append('ul')
64292             .attr('id', 'about-list');
64293
64294         if (!context.embed()) {
64295             aboutList.call(uiAccount(context));
64296         }
64297
64298         aboutList
64299             .append('li')
64300             .append('a')
64301             .attr('target', '_blank')
64302             .attr('tabindex', -1)
64303             .attr('href', 'https://github.com/openstreetmap/iD')
64304             .text(context.version);
64305
64306         var issueLinks = aboutList
64307             .append('li');
64308
64309         issueLinks
64310             .append('a')
64311             .attr('target', '_blank')
64312             .attr('tabindex', -1)
64313             .attr('href', 'https://github.com/openstreetmap/iD/issues')
64314             .call(svgIcon('#icon-bug', 'light'))
64315             .call(tooltip().title(t('report_a_bug')).placement('top'));
64316
64317         issueLinks
64318             .append('a')
64319             .attr('target', '_blank')
64320             .attr('tabindex', -1)
64321             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
64322             .call(svgIcon('#icon-translate', 'light'))
64323             .call(tooltip().title(t('help_translate')).placement('top'));
64324
64325         aboutList
64326             .append('li')
64327             .attr('class', 'feature-warning')
64328             .attr('tabindex', -1)
64329             .call(uiFeatureInfo(context));
64330
64331         aboutList
64332             .append('li')
64333             .attr('class', 'user-list')
64334             .attr('tabindex', -1)
64335             .call(uiContributors(context));
64336
64337
64338         window.onbeforeunload = function() {
64339             return context.save();
64340         };
64341
64342         window.onunload = function() {
64343             context.history().unlock();
64344         };
64345
64346         var mapDimensions = map$$1.dimensions();
64347
64348         function onResize() {
64349             mapDimensions = utilGetDimensions(content, true);
64350             map$$1.dimensions(mapDimensions);
64351         }
64352
64353         select(window)
64354             .on('resize.editor', onResize);
64355
64356         onResize();
64357
64358         function pan(d) {
64359             return function() {
64360                 event.preventDefault();
64361                 if (!context.inIntro()) {
64362                     context.pan(d, 100);
64363                 }
64364             };
64365         }
64366
64367         // pan amount
64368         var pa = 10;
64369
64370         var keybinding = d3keybinding('main')
64371             .on('⌫', function() { event.preventDefault(); })
64372             .on('←', pan([pa, 0]))
64373             .on('↑', pan([0, pa]))
64374             .on('→', pan([-pa, 0]))
64375             .on('↓', pan([0, -pa]))
64376             .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
64377             .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
64378             .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
64379             .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
64380
64381         select(document)
64382             .call(keybinding);
64383
64384         context.enter(modeBrowse$$1(context));
64385
64386         context.container()
64387             .call(uiSplash(context))
64388             .call(uiRestore(context));
64389
64390         var authenticating = uiLoading(context)
64391             .message(t('loading_auth'))
64392             .blocking(true);
64393
64394         context.connection()
64395             .on('authLoading.ui', function() {
64396                 context.container()
64397                     .call(authenticating);
64398             })
64399             .on('authDone.ui', function() {
64400                 authenticating.close();
64401             });
64402     }
64403
64404
64405     function ui(node, callback) {
64406         var container = select(node);
64407         context.container(container);
64408         context.loadLocale(function(err) {
64409             if (!err) {
64410                 render(container);
64411             }
64412             if (callback) {
64413                 callback(err);
64414             }
64415         });
64416     }
64417
64418     ui.sidebar = uiSidebar(context);
64419
64420     return ui;
64421 }
64422
64423 function uiCommit(context) {
64424     var dispatch$$1 = dispatch('cancel', 'save');
64425
64426
64427     function commit(selection$$1) {
64428         var changes = context.history().changes(),
64429             summary = context.history().difference().summary();
64430
64431         selection$$1
64432             .append('div')
64433             .attr('class', 'header fillL')
64434             .append('h3')
64435             .text(t('commit.title'));
64436
64437         var body = selection$$1
64438             .append('div')
64439             .attr('class', 'body');
64440
64441         var commentSection = body
64442             .append('div')
64443             .attr('class', 'modal-section form-field commit-form');
64444
64445         commentSection
64446             .append('label')
64447             .attr('class', 'form-label')
64448             .text(t('commit.message_label'));
64449
64450         var commentField = commentSection
64451             .append('textarea')
64452             .attr('placeholder', t('commit.description_placeholder'))
64453             .attr('maxlength', 255)
64454             .property('value', context.storage('comment') || '')
64455             .on('input.save', checkComment)
64456             .on('change.save', checkComment)
64457             .on('blur.save', function() {
64458                 context.storage('comment', this.value);
64459             });
64460
64461
64462         commentField.node().select();
64463
64464         context.connection().userChangesets(function (err, changesets) {
64465             if (err) return;
64466
64467             var comments = [];
64468
64469             for (var i = 0; i < changesets.length; i++) {
64470                 if (changesets[i].tags.comment) {
64471                     comments.push({
64472                         title: changesets[i].tags.comment,
64473                         value: changesets[i].tags.comment
64474                     });
64475                 }
64476             }
64477
64478             commentField
64479                 .call(d3combobox().caseSensitive(true).data(comments));
64480         });
64481
64482         var clippyArea = commentSection.append('div')
64483             .attr('class', 'clippy-area');
64484
64485         var changeSetInfo = commentSection.append('div')
64486             .attr('class', 'changeset-info');
64487
64488         changeSetInfo.append('a')
64489             .attr('target', '_blank')
64490             .attr('tabindex', -1)
64491             .call(svgIcon('#icon-out-link', 'inline'))
64492             .attr('href', t('commit.about_changeset_comments_link'))
64493             .append('span')
64494             .text(t('commit.about_changeset_comments'));
64495
64496
64497         // Warnings
64498         var warnings = body.selectAll('div.warning-section')
64499             .data([context.history().validate(changes)]);
64500
64501         warnings = warnings.enter()
64502             .append('div')
64503             .attr('class', 'modal-section warning-section fillL2')
64504             .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
64505             .style('background', '#ffb')
64506             .merge(warnings);
64507
64508         warnings
64509             .append('h3')
64510             .text(t('commit.warnings'));
64511
64512         warnings
64513             .append('ul')
64514             .attr('class', 'changeset-list');
64515
64516         var warningLi = warnings.select('ul').selectAll('li')
64517             .data(function(d) { return d; });
64518
64519         warningLi = warningLi.enter()
64520             .append('li')
64521             .on('mouseover', mouseover)
64522             .on('mouseout', mouseout)
64523             .on('click', warningClick)
64524             .merge(warningLi);
64525
64526         warningLi
64527             .call(svgIcon('#icon-alert', 'pre-text'));
64528
64529         warningLi
64530             .append('strong')
64531             .text(function(d) { return d.message; });
64532
64533         warningLi.filter(function(d) { return d.tooltip; })
64534             .call(tooltip()
64535                 .title(function(d) { return d.tooltip; })
64536                 .placement('top')
64537             );
64538
64539
64540         // Upload Explanation
64541         var saveSection = body
64542             .append('div')
64543             .attr('class','modal-section save-section fillL cf');
64544
64545         var prose = saveSection
64546             .append('p')
64547             .attr('class', 'commit-info')
64548             .html(t('commit.upload_explanation'));
64549
64550
64551         context.connection().userDetails(function(err, user) {
64552             if (err) return;
64553
64554             var userLink = select(document.createElement('div'));
64555
64556             if (user.image_url) {
64557                 userLink
64558                     .append('img')
64559                     .attr('src', user.image_url)
64560                     .attr('class', 'icon pre-text user-icon');
64561             }
64562
64563             userLink
64564                 .append('a')
64565                 .attr('class','user-info')
64566                 .text(user.display_name)
64567                 .attr('href', context.connection().userURL(user.display_name))
64568                 .attr('tabindex', -1)
64569                 .attr('target', '_blank');
64570
64571             prose
64572                 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
64573         });
64574
64575
64576         // Buttons
64577         var buttonSection = saveSection
64578             .append('div')
64579             .attr('class','buttons fillL cf');
64580
64581         var cancelButton = buttonSection
64582             .append('button')
64583             .attr('class', 'secondary-action col5 button cancel-button')
64584             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
64585
64586         cancelButton
64587             .append('span')
64588             .attr('class', 'label')
64589             .text(t('commit.cancel'));
64590
64591         var saveButton = buttonSection
64592             .append('button')
64593             .attr('class', 'action col5 button save-button')
64594             .attr('disabled', function() {
64595                 var n = select('.commit-form textarea').node();
64596                 return (n && n.value.length) ? null : true;
64597             })
64598             .on('click.save', function() {
64599                 dispatch$$1.call('save', this, {
64600                     comment: commentField.node().value
64601                 });
64602             });
64603
64604         saveButton
64605             .append('span')
64606             .attr('class', 'label')
64607             .text(t('commit.save'));
64608
64609
64610         // Changes
64611         var changeSection = body
64612             .append('div')
64613             .attr('class', 'commit-section modal-section fillL2');
64614
64615         changeSection.append('h3')
64616             .text(t('commit.changes', { count: summary.length }));
64617
64618         var li = changeSection
64619             .append('ul')
64620             .attr('class', 'changeset-list')
64621             .selectAll('li')
64622             .data(summary);
64623
64624         li = li.enter()
64625             .append('li')
64626             .on('mouseover', mouseover)
64627             .on('mouseout', mouseout)
64628             .on('click', zoomToEntity)
64629             .merge(li);
64630
64631         li.each(function(d) {
64632             select(this)
64633                 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
64634         });
64635
64636         li.append('span')
64637             .attr('class', 'change-type')
64638             .text(function(d) { return t('commit.' + d.changeType) + ' '; });
64639
64640         li.append('strong')
64641             .attr('class', 'entity-type')
64642             .text(function(d) {
64643                 var matched = context.presets().match(d.entity, d.graph);
64644                 return (matched && matched.name()) || utilDisplayType(d.entity.id);
64645             });
64646
64647         li.append('span')
64648             .attr('class', 'entity-name')
64649             .text(function(d) {
64650                 var name = utilDisplayName(d.entity) || '',
64651                     string = '';
64652                 if (name !== '') string += ':';
64653                 return string += ' ' + name;
64654             });
64655
64656         li.style('opacity', 0)
64657             .transition()
64658             .style('opacity', 1);
64659
64660
64661         // Call checkComment off the bat, in case a changeset
64662         // comment is recovered from localStorage
64663         utilTriggerEvent(commentField, 'input');
64664
64665
64666         function mouseover(d) {
64667             if (d.entity) {
64668                 context.surface().selectAll(
64669                     utilEntityOrMemberSelector([d.entity.id], context.graph())
64670                 ).classed('hover', true);
64671             }
64672         }
64673
64674
64675         function mouseout() {
64676             context.surface().selectAll('.hover')
64677                 .classed('hover', false);
64678         }
64679
64680
64681         function warningClick(d) {
64682             if (d.entity) {
64683                 context.map().zoomTo(d.entity);
64684                 context.enter(
64685                     modeSelect(context, [d.entity.id]).suppressMenu(true)
64686                 );
64687             }
64688         }
64689
64690
64691         function zoomToEntity(change) {
64692             var entity = change.entity;
64693             if (change.changeType !== 'deleted' &&
64694                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
64695                 context.map().zoomTo(entity);
64696                 context.surface().selectAll(
64697                     utilEntityOrMemberSelector([entity.id], context.graph()))
64698                     .classed('hover', true);
64699             }
64700         }
64701
64702
64703         function checkComment() {
64704             selectAll('.save-section .save-button')
64705                 .attr('disabled', (this.value.length ? null : true));
64706
64707             var googleWarning = clippyArea
64708                .html('')
64709                .selectAll('a')
64710                .data(this.value.match(/google/i) ? [true] : []);
64711
64712             googleWarning.exit()
64713                 .remove();
64714
64715             googleWarning.enter()
64716                .append('a')
64717                .attr('target', '_blank')
64718                .attr('tabindex', -1)
64719                .call(svgIcon('#icon-alert', 'inline'))
64720                .attr('href', t('commit.google_warning_link'))
64721                .append('span')
64722                .text(t('commit.google_warning'));
64723         }
64724     }
64725
64726     return utilRebind(commit, dispatch$$1, 'on');
64727 }
64728
64729 function uiConfirm(selection) {
64730     var modalSelection = uiModal(selection);
64731
64732     modalSelection.select('.modal')
64733         .classed('modal-alert', true);
64734
64735     var section = modalSelection.select('.content');
64736
64737     section.append('div')
64738         .attr('class', 'modal-section header');
64739
64740     section.append('div')
64741         .attr('class', 'modal-section message-text');
64742
64743     var buttons = section.append('div')
64744         .attr('class', 'modal-section buttons cf');
64745
64746
64747     modalSelection.okButton = function() {
64748         buttons
64749             .append('button')
64750             .attr('class', 'action col4')
64751             .on('click.confirm', function() {
64752                 modalSelection.remove();
64753             })
64754             .text(t('confirm.okay'));
64755
64756         return modalSelection;
64757     };
64758
64759
64760     return modalSelection;
64761 }
64762
64763 function uiConflicts(context) {
64764     var dispatch$$1 = dispatch('download', 'cancel', 'save'),
64765         list;
64766
64767
64768     function conflicts(selection$$1) {
64769         var header = selection$$1
64770             .append('div')
64771             .attr('class', 'header fillL');
64772
64773         header
64774             .append('button')
64775             .attr('class', 'fr')
64776             .on('click', function() { dispatch$$1.call('cancel'); })
64777             .call(svgIcon('#icon-close'));
64778
64779         header
64780             .append('h3')
64781             .text(t('save.conflict.header'));
64782
64783         var body = selection$$1
64784             .append('div')
64785             .attr('class', 'body fillL');
64786
64787         body
64788             .append('div')
64789             .attr('class', 'conflicts-help')
64790             .text(t('save.conflict.help'))
64791             .append('a')
64792             .attr('class', 'conflicts-download')
64793             .text(t('save.conflict.download_changes'))
64794             .on('click.download', function() { dispatch$$1.call('download'); });
64795
64796         body
64797             .append('div')
64798             .attr('class', 'conflict-container fillL3')
64799             .call(showConflict, 0);
64800
64801         body
64802             .append('div')
64803             .attr('class', 'conflicts-done')
64804             .attr('opacity', 0)
64805             .style('display', 'none')
64806             .text(t('save.conflict.done'));
64807
64808         var buttons = body
64809             .append('div')
64810             .attr('class','buttons col12 joined conflicts-buttons');
64811
64812         buttons
64813             .append('button')
64814             .attr('disabled', list.length > 1)
64815             .attr('class', 'action conflicts-button col6')
64816             .text(t('save.title'))
64817             .on('click.try_again', function() { dispatch$$1.call('save'); });
64818
64819         buttons
64820             .append('button')
64821             .attr('class', 'secondary-action conflicts-button col6')
64822             .text(t('confirm.cancel'))
64823             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
64824     }
64825
64826
64827     function showConflict(selection$$1, index) {
64828         if (index < 0 || index >= list.length) return;
64829
64830         var parent = select(selection$$1.node().parentNode);
64831
64832         // enable save button if this is the last conflict being reviewed..
64833         if (index === list.length - 1) {
64834             window.setTimeout(function() {
64835                 parent.select('.conflicts-button')
64836                     .attr('disabled', null);
64837
64838                 parent.select('.conflicts-done')
64839                     .transition()
64840                     .attr('opacity', 1)
64841                     .style('display', 'block');
64842             }, 250);
64843         }
64844
64845         var item = selection$$1
64846             .selectAll('.conflict')
64847             .data([list[index]]);
64848
64849         var enter = item.enter()
64850             .append('div')
64851             .attr('class', 'conflict');
64852
64853         enter
64854             .append('h4')
64855             .attr('class', 'conflict-count')
64856             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
64857
64858         enter
64859             .append('a')
64860             .attr('class', 'conflict-description')
64861             .attr('href', '#')
64862             .text(function(d) { return d.name; })
64863             .on('click', function(d) {
64864                 zoomToEntity(d.id);
64865                 event.preventDefault();
64866             });
64867
64868         var details = enter
64869             .append('div')
64870             .attr('class', 'conflict-detail-container');
64871
64872         details
64873             .append('ul')
64874             .attr('class', 'conflict-detail-list')
64875             .selectAll('li')
64876             .data(function(d) { return d.details || []; })
64877             .enter()
64878             .append('li')
64879             .attr('class', 'conflict-detail-item')
64880             .html(function(d) { return d; });
64881
64882         details
64883             .append('div')
64884             .attr('class', 'conflict-choices')
64885             .call(addChoices);
64886
64887         details
64888             .append('div')
64889             .attr('class', 'conflict-nav-buttons joined cf')
64890             .selectAll('button')
64891             .data(['previous', 'next'])
64892             .enter()
64893             .append('button')
64894             .text(function(d) { return t('save.conflict.' + d); })
64895             .attr('class', 'conflict-nav-button action col6')
64896             .attr('disabled', function(d, i) {
64897                 return (i === 0 && index === 0) ||
64898                     (i === 1 && index === list.length - 1) || null;
64899             })
64900             .on('click', function(d, i) {
64901                 var container = parent.select('.conflict-container'),
64902                 sign = (i === 0 ? -1 : 1);
64903
64904                 container
64905                     .selectAll('.conflict')
64906                     .remove();
64907
64908                 container
64909                     .call(showConflict, index + sign);
64910
64911                 event.preventDefault();
64912             });
64913
64914         item.exit()
64915             .remove();
64916     }
64917
64918
64919     function addChoices(selection$$1) {
64920         var choices = selection$$1
64921             .append('ul')
64922             .attr('class', 'layer-list')
64923             .selectAll('li')
64924             .data(function(d) { return d.choices || []; });
64925
64926         var enter = choices.enter()
64927             .append('li')
64928             .attr('class', 'layer');
64929
64930         var label = enter
64931             .append('label');
64932
64933         label
64934             .append('input')
64935             .attr('type', 'radio')
64936             .attr('name', function(d) { return d.id; })
64937             .on('change', function(d, i) {
64938                 var ul = this.parentNode.parentNode.parentNode;
64939                 ul.__data__.chosen = i;
64940                 choose(ul, d);
64941             });
64942
64943         label
64944             .append('span')
64945             .text(function(d) { return d.text; });
64946
64947         choices
64948             .each(function(d, i) {
64949                 var ul = this.parentNode;
64950                 if (ul.__data__.chosen === i) choose(ul, d);
64951             });
64952     }
64953
64954
64955     function choose(ul, datum) {
64956         if (event) event.preventDefault();
64957
64958         select(ul)
64959             .selectAll('li')
64960             .classed('active', function(d) { return d === datum; })
64961             .selectAll('input')
64962             .property('checked', function(d) { return d === datum; });
64963
64964         var extent$$1 = geoExtent$$1(),
64965             entity;
64966
64967         entity = context.graph().hasEntity(datum.id);
64968         if (entity) extent$$1._extend(entity.extent(context.graph()));
64969
64970         datum.action();
64971
64972         entity = context.graph().hasEntity(datum.id);
64973         if (entity) extent$$1._extend(entity.extent(context.graph()));
64974
64975         zoomToEntity(datum.id, extent$$1);
64976     }
64977
64978
64979     function zoomToEntity(id, extent$$1) {
64980         context.surface().selectAll('.hover')
64981             .classed('hover', false);
64982
64983         var entity = context.graph().hasEntity(id);
64984         if (entity) {
64985             if (extent$$1) {
64986                 context.map().trimmedExtent(extent$$1);
64987             } else {
64988                 context.map().zoomTo(entity);
64989             }
64990             context.surface().selectAll(
64991                 utilEntityOrMemberSelector([entity.id], context.graph()))
64992                 .classed('hover', true);
64993         }
64994     }
64995
64996
64997     // The conflict list should be an array of objects like:
64998     // {
64999     //     id: id,
65000     //     name: entityName(local),
65001     //     details: merge.conflicts(),
65002     //     chosen: 1,
65003     //     choices: [
65004     //         choice(id, keepMine, forceLocal),
65005     //         choice(id, keepTheirs, forceRemote)
65006     //     ]
65007     // }
65008     conflicts.list = function(_) {
65009         if (!arguments.length) return list;
65010         list = _;
65011         return conflicts;
65012     };
65013
65014
65015     return utilRebind(conflicts, dispatch$$1, 'on');
65016 }
65017
65018 function uiFlash(selection) {
65019     var modalSelection = uiModal(selection);
65020
65021     modalSelection.select('.modal')
65022         .classed('modal-flash', true);
65023
65024     modalSelection.select('.content')
65025         .classed('modal-section', true)
65026         .append('div')
65027         .attr('class', 'description');
65028
65029     modalSelection.on('click.flash', function() {
65030         modalSelection.remove();
65031     });
65032
65033     setTimeout(function() {
65034         modalSelection.remove();
65035         return true;
65036     }, 1500);
65037
65038
65039     return modalSelection;
65040 }
65041
65042 function uiLasso(context) {
65043     var group, polygon;
65044
65045     lasso.coordinates = [];
65046
65047     function lasso(selection$$1) {
65048         context.container()
65049             .classed('lasso', true);
65050
65051         group = selection$$1
65052             .append('g')
65053             .attr('class', 'lasso hide');
65054
65055         polygon = group
65056             .append('path')
65057             .attr('class', 'lasso-path');
65058
65059         group
65060             .call(uiToggle(true));
65061     }
65062
65063
65064     function draw() {
65065         if (polygon) {
65066             polygon.data([lasso.coordinates])
65067                 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
65068         }
65069     }
65070
65071
65072     lasso.extent = function () {
65073         return lasso.coordinates.reduce(function(extent$$1, point) {
65074             return extent$$1.extend(geoExtent$$1(point));
65075         }, geoExtent$$1());
65076     };
65077
65078
65079     lasso.p = function(_) {
65080         if (!arguments.length) return lasso;
65081         lasso.coordinates.push(_);
65082         draw();
65083         return lasso;
65084     };
65085
65086
65087     lasso.close = function() {
65088         if (group) {
65089             group.call(uiToggle(false, function() {
65090                 select(this).remove();
65091             }));
65092         }
65093         context.container().classed('lasso', false);
65094     };
65095
65096
65097     return lasso;
65098 }
65099
65100 function uiRadialMenu(context, operations) {
65101     var menu,
65102         center = [0, 0],
65103         tooltip;
65104
65105
65106     var radialMenu = function(selection$$1) {
65107         if (!operations.length) return;
65108
65109         selection$$1.node().parentNode.focus();
65110
65111         function click(operation) {
65112             event.stopPropagation();
65113             if (operation.disabled()) return;
65114             operation();
65115             radialMenu.close();
65116         }
65117
65118         menu = selection$$1
65119             .append('g')
65120             .attr('class', 'radial-menu')
65121             .attr('transform', 'translate(' + center + ')')
65122             .attr('opacity', 0);
65123
65124         menu
65125             .transition()
65126             .attr('opacity', 1);
65127
65128         var r = 50,
65129             a = Math.PI / 4,
65130             a0 = -Math.PI / 4,
65131             a1 = a0 + (operations.length - 1) * a;
65132
65133         menu
65134             .append('path')
65135             .attr('class', 'radial-menu-background')
65136             .attr('d', 'M' + r * Math.sin(a0) + ',' +
65137                              r * Math.cos(a0) +
65138                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
65139                              (r * Math.sin(a1) + 1e-3) + ',' +
65140                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
65141             .attr('stroke-width', 50)
65142             .attr('stroke-linecap', 'round');
65143
65144         var button = menu.selectAll()
65145             .data(operations)
65146             .enter()
65147             .append('g')
65148             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
65149             .classed('disabled', function(d) { return d.disabled(); })
65150             .attr('transform', function(d, i) {
65151                 return 'translate(' + geoRoundCoords([
65152                         r * Math.sin(a0 + i * a),
65153                         r * Math.cos(a0 + i * a)]).join(',') + ')';
65154             });
65155
65156         button
65157             .append('circle')
65158             .attr('r', 15)
65159             .on('click', click)
65160             .on('mousedown', mousedown)
65161             .on('mouseover', mouseover)
65162             .on('mouseout', mouseout);
65163
65164         button
65165             .append('use')
65166             .attr('transform', 'translate(-10,-10)')
65167             .attr('width', '20')
65168             .attr('height', '20')
65169             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
65170
65171         tooltip = select(document.body)
65172             .append('div')
65173             .attr('class', 'tooltip-inner radial-menu-tooltip');
65174
65175         function mousedown() {
65176             event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
65177         }
65178
65179         function mouseover(d, i) {
65180             var rect = context.surfaceRect(),
65181                 angle = a0 + i * a,
65182                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
65183                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
65184                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
65185                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
65186
65187             tooltip
65188                 .style('top', null)
65189                 .style('left', null)
65190                 .style('bottom', null)
65191                 .style('right', null)
65192                 .style('display', 'block')
65193                 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
65194
65195             if (i === 0) {
65196                 tooltip
65197                     .style('right', right)
65198                     .style('top', top);
65199             } else if (i >= 4) {
65200                 tooltip
65201                     .style('left', left)
65202                     .style('bottom', bottom);
65203             } else {
65204                 tooltip
65205                     .style('left', left)
65206                     .style('top', top);
65207             }
65208         }
65209
65210         function mouseout() {
65211             tooltip.style('display', 'none');
65212         }
65213     };
65214
65215
65216     radialMenu.close = function() {
65217         if (menu) {
65218             menu
65219                 .style('pointer-events', 'none')
65220                 .transition()
65221                 .attr('opacity', 0)
65222                 .remove();
65223         }
65224
65225         if (tooltip) {
65226             tooltip.remove();
65227         }
65228     };
65229
65230
65231     radialMenu.center = function(_) {
65232         if (!arguments.length) return center;
65233         center = _;
65234         return radialMenu;
65235     };
65236
65237
65238     return radialMenu;
65239 }
65240
65241 function uiSelectionList(context, selectedIDs) {
65242
65243     function selectEntity(entity) {
65244         context.enter(modeSelect(context, [entity.id]).suppressMenu(true));
65245     }
65246
65247
65248     function deselectEntity(entity) {
65249         event.stopPropagation();
65250         var index = selectedIDs.indexOf(entity.id);
65251         if (index > -1) {
65252             selectedIDs.splice(index, 1);
65253         }
65254         context.enter(modeSelect(context, selectedIDs).suppressMenu(true));
65255     }
65256
65257
65258     function selectionList(selection$$1) {
65259         selection$$1.classed('selection-list-pane', true);
65260
65261         var header = selection$$1
65262             .append('div')
65263             .attr('class', 'header fillL cf');
65264
65265         header
65266             .append('h3')
65267             .text(t('inspector.multiselect'));
65268
65269         var listWrap = selection$$1
65270             .append('div')
65271             .attr('class', 'inspector-body');
65272
65273         var list = listWrap
65274             .append('div')
65275             .attr('class', 'feature-list cf');
65276
65277         context.history().on('change.selection-list', drawList);
65278         drawList();
65279
65280
65281         function drawList() {
65282             var entities = selectedIDs
65283                 .map(function(id) { return context.hasEntity(id); })
65284                 .filter(function(entity) { return entity; });
65285
65286             var items = list.selectAll('.feature-list-item')
65287                 .data(entities, osmEntity$$1.key);
65288
65289             items.exit()
65290                 .remove();
65291
65292             // Enter
65293             var enter = items.enter()
65294                 .append('div')
65295                 .attr('class', 'feature-list-item')
65296                 .on('click', selectEntity);
65297
65298             var label = enter
65299                 .append('button')
65300                 .attr('class', 'label');
65301
65302             enter
65303                 .append('button')
65304                 .attr('class', 'close')
65305                 .on('click', deselectEntity)
65306                 .call(svgIcon('#icon-close'));
65307
65308             label
65309                 .append('span')
65310                 .attr('class', 'entity-geom-icon')
65311                 .call(svgIcon('', 'pre-text'));
65312
65313             label
65314                 .append('span')
65315                 .attr('class', 'entity-type');
65316
65317             label
65318                 .append('span')
65319                 .attr('class', 'entity-name');
65320
65321             // Update
65322             items = items.merge(enter);
65323
65324             items.selectAll('.entity-geom-icon use')
65325                 .attr('href', function() {
65326                     var entity = this.parentNode.parentNode.__data__;
65327                     return '#icon-' + context.geometry(entity.id);
65328                 });
65329
65330             items.selectAll('.entity-type')
65331                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
65332
65333             items.selectAll('.entity-name')
65334                 .text(function(entity) { return utilDisplayName(entity); });
65335         }
65336     }
65337
65338     return selectionList;
65339 }
65340
65341 function uiSourceSwitch(context) {
65342     var keys$$1;
65343
65344
65345     function click() {
65346         event.preventDefault();
65347
65348         if (context.history().hasChanges() &&
65349             !window.confirm(t('source_switch.lose_changes'))) return;
65350
65351         var live = select(this)
65352             .classed('live');
65353
65354         context.connection()
65355             .switch(live ? keys$$1[1] : keys$$1[0]);
65356
65357         context.enter(modeBrowse$$1(context));
65358         context.flush();
65359
65360         select(this)
65361             .text(live ? t('source_switch.dev') : t('source_switch.live'))
65362             .classed('live', !live);
65363     }
65364
65365     var sourceSwitch = function(selection$$1) {
65366         selection$$1
65367             .append('a')
65368             .attr('href', '#')
65369             .text(t('source_switch.live'))
65370             .classed('live', true)
65371             .attr('tabindex', -1)
65372             .on('click', click);
65373     };
65374
65375
65376     sourceSwitch.keys = function(_) {
65377         if (!arguments.length) return keys$$1;
65378         keys$$1 = _;
65379         return sourceSwitch;
65380     };
65381
65382
65383     return sourceSwitch;
65384 }
65385
65386 function uiSuccess(context) {
65387     var dispatch$$1 = dispatch('cancel'),
65388         changeset;
65389
65390
65391     function success(selection$$1) {
65392         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
65393             ' ' + context.connection().changesetURL(changeset.id);
65394
65395         var header = selection$$1
65396             .append('div')
65397             .attr('class', 'header fillL');
65398
65399         header
65400             .append('button')
65401             .attr('class', 'fr')
65402             .on('click', function() { dispatch$$1.call('cancel'); })
65403             .call(svgIcon('#icon-close'));
65404
65405         header
65406             .append('h3')
65407             .text(t('success.just_edited'));
65408
65409         var body = selection$$1
65410             .append('div')
65411             .attr('class', 'body save-success fillL');
65412
65413         body
65414             .append('p')
65415             .html(t('success.help_html'));
65416
65417         body
65418             .append('a')
65419             .attr('class', 'details')
65420             .attr('target', '_blank')
65421             .attr('tabindex', -1)
65422             .call(svgIcon('#icon-out-link', 'inline'))
65423             .attr('href', t('success.help_link_url'))
65424             .append('span')
65425             .text(t('success.help_link_text'));
65426
65427         var changesetURL = context.connection().changesetURL(changeset.id);
65428
65429         body
65430             .append('a')
65431             .attr('class', 'button col12 osm')
65432             .attr('target', '_blank')
65433             .attr('href', changesetURL)
65434             .text(t('success.view_on_osm'));
65435
65436         var sharing = {
65437             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
65438             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
65439             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
65440         };
65441
65442         body.selectAll('.button.social')
65443             .data(entries(sharing))
65444             .enter()
65445             .append('a')
65446             .attr('class', 'button social col4')
65447             .attr('target', '_blank')
65448             .attr('href', function(d) { return d.value; })
65449             .call(tooltip()
65450                 .title(function(d) { return t('success.' + d.key); })
65451                 .placement('bottom'))
65452             .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
65453     }
65454
65455
65456     success.changeset = function(_) {
65457         if (!arguments.length) return changeset;
65458         changeset = _;
65459         return success;
65460     };
65461
65462
65463     return utilRebind(success, dispatch$$1, 'on');
65464 }
65465
65466 function coreHistory(context) {
65467     var stack$$1, index, tree$$1,
65468         imageryUsed = ['Bing'],
65469         dispatch$$1 = dispatch('change', 'undone', 'redone'),
65470         lock = utilSessionMutex('lock');
65471
65472
65473     function perform(actions) {
65474         actions = Array.prototype.slice.call(actions);
65475
65476         var annotation;
65477
65478         if (!lodash.isFunction(lodash.last(actions))) {
65479             annotation = actions.pop();
65480         }
65481
65482         var graph = stack$$1[index].graph;
65483         for (var i = 0; i < actions.length; i++) {
65484             graph = actions[i](graph);
65485         }
65486
65487         return {
65488             graph: graph,
65489             annotation: annotation,
65490             imageryUsed: imageryUsed
65491         };
65492     }
65493
65494
65495     function change(previous) {
65496         var difference = coreDifference(previous, history.graph());
65497         dispatch$$1.call('change', this, difference);
65498         return difference;
65499     }
65500
65501
65502     // iD uses namespaced keys so multiple installations do not conflict
65503     function getKey(n) {
65504         return 'iD_' + window.location.origin + '_' + n;
65505     }
65506
65507
65508     var history = {
65509
65510         graph: function() {
65511             return stack$$1[index].graph;
65512         },
65513
65514
65515         base: function() {
65516             return stack$$1[0].graph;
65517         },
65518
65519
65520         merge: function(entities, extent$$1) {
65521             stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
65522             tree$$1.rebase(entities, false);
65523
65524             dispatch$$1.call('change', this, undefined, extent$$1);
65525         },
65526
65527
65528         perform: function() {
65529             var previous = stack$$1[index].graph;
65530
65531             stack$$1 = stack$$1.slice(0, index + 1);
65532             stack$$1.push(perform(arguments));
65533             index++;
65534
65535             return change(previous);
65536         },
65537
65538
65539         replace: function() {
65540             var previous = stack$$1[index].graph;
65541
65542             // assert(index == stack.length - 1)
65543             stack$$1[index] = perform(arguments);
65544
65545             return change(previous);
65546         },
65547
65548
65549         pop: function() {
65550             var previous = stack$$1[index].graph;
65551
65552             if (index > 0) {
65553                 index--;
65554                 stack$$1.pop();
65555                 return change(previous);
65556             }
65557         },
65558
65559
65560         // Same as calling pop and then perform
65561         overwrite: function() {
65562             var previous = stack$$1[index].graph;
65563
65564             if (index > 0) {
65565                 index--;
65566                 stack$$1.pop();
65567             }
65568             stack$$1 = stack$$1.slice(0, index + 1);
65569             stack$$1.push(perform(arguments));
65570             index++;
65571
65572             return change(previous);
65573         },
65574
65575
65576         undo: function() {
65577             var previous = stack$$1[index].graph;
65578
65579             // Pop to the next annotated state.
65580             while (index > 0) {
65581                 index--;
65582                 if (stack$$1[index].annotation) break;
65583             }
65584
65585             dispatch$$1.call('undone');
65586             return change(previous);
65587         },
65588
65589
65590         redo: function() {
65591             var previous = stack$$1[index].graph;
65592
65593             while (index < stack$$1.length - 1) {
65594                 index++;
65595                 if (stack$$1[index].annotation) break;
65596             }
65597
65598             dispatch$$1.call('redone');
65599             return change(previous);
65600         },
65601
65602
65603         undoAnnotation: function() {
65604             var i = index;
65605             while (i >= 0) {
65606                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
65607                 i--;
65608             }
65609         },
65610
65611
65612         redoAnnotation: function() {
65613             var i = index + 1;
65614             while (i <= stack$$1.length - 1) {
65615                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
65616                 i++;
65617             }
65618         },
65619
65620
65621         intersects: function(extent$$1) {
65622             return tree$$1.intersects(extent$$1, stack$$1[index].graph);
65623         },
65624
65625
65626         difference: function() {
65627             var base = stack$$1[0].graph,
65628                 head = stack$$1[index].graph;
65629             return coreDifference(base, head);
65630         },
65631
65632
65633         changes: function(action) {
65634             var base = stack$$1[0].graph,
65635                 head = stack$$1[index].graph;
65636
65637             if (action) {
65638                 head = action(head);
65639             }
65640
65641             var difference = coreDifference(base, head);
65642
65643             return {
65644                 modified: difference.modified(),
65645                 created: difference.created(),
65646                 deleted: difference.deleted()
65647             };
65648         },
65649
65650
65651         validate: function(changes) {
65652             return lodash(Validations)
65653                 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
65654                 .flatten()
65655                 .value();
65656         },
65657
65658
65659         hasChanges: function() {
65660             return this.difference().length() > 0;
65661         },
65662
65663
65664         imageryUsed: function(sources) {
65665             if (sources) {
65666                 imageryUsed = sources;
65667                 return history;
65668             } else {
65669                 return lodash(stack$$1.slice(1, index + 1))
65670                     .map('imageryUsed')
65671                     .flatten()
65672                     .uniq()
65673                     .without(undefined, 'Custom')
65674                     .value();
65675             }
65676         },
65677
65678
65679         reset: function() {
65680             stack$$1 = [{graph: coreGraph$$1()}];
65681             index = 0;
65682             tree$$1 = coreTree(stack$$1[0].graph);
65683             dispatch$$1.call('change');
65684             return history;
65685         },
65686
65687
65688         toJSON: function() {
65689             if (!this.hasChanges()) return;
65690
65691             var allEntities = {},
65692                 baseEntities = {},
65693                 base = stack$$1[0];
65694
65695             var s = stack$$1.map(function(i) {
65696                 var modified = [], deleted = [];
65697
65698                 lodash.forEach(i.graph.entities, function(entity, id) {
65699                     if (entity) {
65700                         var key = osmEntity$$1.key(entity);
65701                         allEntities[key] = entity;
65702                         modified.push(key);
65703                     } else {
65704                         deleted.push(id);
65705                     }
65706
65707                     // make sure that the originals of changed or deleted entities get merged
65708                     // into the base of the stack after restoring the data from JSON.
65709                     if (id in base.graph.entities) {
65710                         baseEntities[id] = base.graph.entities[id];
65711                     }
65712                     // get originals of parent entities too
65713                     lodash.forEach(base.graph._parentWays[id], function(parentId) {
65714                         if (parentId in base.graph.entities) {
65715                             baseEntities[parentId] = base.graph.entities[parentId];
65716                         }
65717                     });
65718                 });
65719
65720                 var x = {};
65721
65722                 if (modified.length) x.modified = modified;
65723                 if (deleted.length) x.deleted = deleted;
65724                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
65725                 if (i.annotation) x.annotation = i.annotation;
65726
65727                 return x;
65728             });
65729
65730             return JSON.stringify({
65731                 version: 3,
65732                 entities: lodash.values(allEntities),
65733                 baseEntities: lodash.values(baseEntities),
65734                 stack: s,
65735                 nextIDs: osmEntity$$1.id.next,
65736                 index: index
65737             });
65738         },
65739
65740
65741         fromJSON: function(json$$1, loadChildNodes) {
65742             var h = JSON.parse(json$$1),
65743                 loadComplete = true;
65744
65745             osmEntity$$1.id.next = h.nextIDs;
65746             index = h.index;
65747
65748             if (h.version === 2 || h.version === 3) {
65749                 var allEntities = {};
65750
65751                 h.entities.forEach(function(entity) {
65752                     allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
65753                 });
65754
65755                 if (h.version === 3) {
65756                     // This merges originals for changed entities into the base of
65757                     // the stack even if the current stack doesn't have them (for
65758                     // example when iD has been restarted in a different region)
65759                     var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
65760                     stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
65761                     tree$$1.rebase(baseEntities, true);
65762
65763                     // When we restore a modified way, we also need to fetch any missing
65764                     // childnodes that would normally have been downloaded with it.. #2142
65765                     if (loadChildNodes) {
65766                         var missing =  lodash(baseEntities)
65767                                 .filter({ type: 'way' })
65768                                 .map('nodes')
65769                                 .flatten()
65770                                 .uniq()
65771                                 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
65772                                 .value();
65773
65774                         if (!lodash.isEmpty(missing)) {
65775                             loadComplete = false;
65776                             context.redrawEnable(false);
65777
65778                             var loading = uiLoading(context).blocking(true);
65779                             context.container().call(loading);
65780
65781                             var childNodesLoaded = function(err, result) {
65782                                 if (!err) {
65783                                     var visible = lodash.groupBy(result.data, 'visible');
65784                                     if (!lodash.isEmpty(visible.true)) {
65785                                         missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
65786                                         stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
65787                                         tree$$1.rebase(visible.true, true);
65788                                     }
65789
65790                                     // fetch older versions of nodes that were deleted..
65791                                     lodash.each(visible.false, function(entity) {
65792                                         context.connection()
65793                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
65794                                     });
65795                                 }
65796
65797                                 if (err || lodash.isEmpty(missing)) {
65798                                     loading.close();
65799                                     context.redrawEnable(true);
65800                                     dispatch$$1.call('change');
65801                                 }
65802                             };
65803
65804                             context.connection().loadMultiple(missing, childNodesLoaded);
65805                         }
65806                     }
65807                 }
65808
65809                 stack$$1 = h.stack.map(function(d) {
65810                     var entities = {}, entity;
65811
65812                     if (d.modified) {
65813                         d.modified.forEach(function(key) {
65814                             entity = allEntities[key];
65815                             entities[entity.id] = entity;
65816                         });
65817                     }
65818
65819                     if (d.deleted) {
65820                         d.deleted.forEach(function(id) {
65821                             entities[id] = undefined;
65822                         });
65823                     }
65824
65825                     return {
65826                         graph: coreGraph$$1(stack$$1[0].graph).load(entities),
65827                         annotation: d.annotation,
65828                         imageryUsed: d.imageryUsed
65829                     };
65830                 });
65831
65832             } else { // original version
65833                 stack$$1 = h.stack.map(function(d) {
65834                     var entities = {};
65835
65836                     for (var i in d.entities) {
65837                         var entity = d.entities[i];
65838                         entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
65839                     }
65840
65841                     d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
65842                     return d;
65843                 });
65844             }
65845
65846             if (loadComplete) {
65847                 dispatch$$1.call('change');
65848             }
65849
65850             return history;
65851         },
65852
65853
65854         save: function() {
65855             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
65856             return history;
65857         },
65858
65859
65860         clearSaved: function() {
65861             context.debouncedSave.cancel();
65862             if (lock.locked()) context.storage(getKey('saved_history'), null);
65863             return history;
65864         },
65865
65866
65867         lock: function() {
65868             return lock.lock();
65869         },
65870
65871
65872         unlock: function() {
65873             lock.unlock();
65874         },
65875
65876
65877         // is iD not open in another window and it detects that
65878         // there's a history stored in localStorage that's recoverable?
65879         restorableChanges: function() {
65880             return lock.locked() && !!context.storage(getKey('saved_history'));
65881         },
65882
65883
65884         // load history from a version stored in localStorage
65885         restore: function() {
65886             if (!lock.locked()) return;
65887
65888             var json$$1 = context.storage(getKey('saved_history'));
65889             if (json$$1) history.fromJSON(json$$1, true);
65890         },
65891
65892
65893         _getKey: getKey
65894
65895     };
65896
65897
65898     history.reset();
65899
65900     return utilRebind(history, dispatch$$1, 'on');
65901 }
65902
65903 function presetCollection(collection) {
65904     var maxSearchResults = 50,
65905         maxSuggestionResults = 10;
65906
65907     var presets = {
65908
65909         collection: collection,
65910
65911
65912         item: function(id) {
65913             return lodash.find(collection, function(d) {
65914                 return d.id === id;
65915             });
65916         },
65917
65918
65919         matchGeometry: function(geometry) {
65920             return presetCollection(collection.filter(function(d) {
65921                 return d.matchGeometry(geometry);
65922             }));
65923         },
65924
65925
65926         search: function(value, geometry) {
65927             if (!value) return this;
65928
65929             function leading(a) {
65930                 var index = a.indexOf(value);
65931                 return index === 0 || a[index - 1] === ' ';
65932             }
65933
65934             function suggestionName(name) {
65935                 var nameArray = name.split(' - ');
65936                 if (nameArray.length > 1) {
65937                     name = nameArray.slice(0, nameArray.length - 1).join(' - ');
65938                 }
65939                 return name.toLowerCase();
65940             }
65941
65942
65943             value = value.toLowerCase();
65944
65945             var searchable = lodash.filter(collection, function(a) {
65946                     return a.searchable !== false && a.suggestion !== true;
65947                 }),
65948                 suggestions = lodash.filter(collection, function(a) {
65949                     return a.suggestion === true;
65950                 });
65951
65952
65953             // matches value to preset.name
65954             var leading_name = lodash.filter(searchable, function(a) {
65955                     return leading(a.name().toLowerCase());
65956                 }).sort(function(a, b) {
65957                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
65958                     if (i === 0) return a.name().length - b.name().length;
65959                     else return i;
65960                 });
65961
65962             // matches value to preset.terms values
65963             var leading_terms = lodash.filter(searchable, function(a) {
65964                     return lodash.some(a.terms() || [], leading);
65965                 });
65966
65967             // matches value to preset.tags values
65968             var leading_tag_values = lodash.filter(searchable, function(a) {
65969                     return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
65970                 });
65971
65972
65973             // finds close matches to value in preset.name
65974             var similar_name = searchable.map(function(a) {
65975                     return {
65976                         preset: a,
65977                         dist: utilEditDistance(value, a.name())
65978                     };
65979                 }).filter(function(a) {
65980                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
65981                 }).sort(function(a, b) {
65982                     return a.dist - b.dist;
65983                 }).map(function(a) {
65984                     return a.preset;
65985                 });
65986
65987             // finds close matches to value in preset.terms
65988             var similar_terms = lodash.filter(searchable, function(a) {
65989                     return lodash.some(a.terms() || [], function(b) {
65990                         return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
65991                     });
65992                 });
65993
65994             var leading_suggestions = lodash.filter(suggestions, function(a) {
65995                     return leading(suggestionName(a.name()));
65996                 }).sort(function(a, b) {
65997                     a = suggestionName(a.name());
65998                     b = suggestionName(b.name());
65999                     var i = a.indexOf(value) - b.indexOf(value);
66000                     if (i === 0) return a.length - b.length;
66001                     else return i;
66002                 });
66003
66004             var similar_suggestions = suggestions.map(function(a) {
66005                     return {
66006                         preset: a,
66007                         dist: utilEditDistance(value, suggestionName(a.name()))
66008                     };
66009                 }).filter(function(a) {
66010                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
66011                 }).sort(function(a, b) {
66012                     return a.dist - b.dist;
66013                 }).map(function(a) {
66014                     return a.preset;
66015                 });
66016
66017             var other = presets.item(geometry);
66018
66019             var results = leading_name.concat(
66020                     leading_terms,
66021                     leading_tag_values,
66022                     leading_suggestions.slice(0, maxSuggestionResults + 5),
66023                     similar_name,
66024                     similar_terms,
66025                     similar_suggestions.slice(0, maxSuggestionResults)
66026                 ).slice(0, maxSearchResults - 1);
66027
66028             return presetCollection(lodash.uniq(results.concat(other)));
66029         }
66030     };
66031
66032
66033     return presets;
66034 }
66035
66036 function presetCategory(id, category, all) {
66037     category = lodash.clone(category);
66038
66039     category.id = id;
66040
66041
66042     category.members = presetCollection(category.members.map(function(id) {
66043         return all.item(id);
66044     }));
66045
66046
66047     category.matchGeometry = function(geometry) {
66048         return category.geometry.indexOf(geometry) >= 0;
66049     };
66050
66051
66052     category.matchScore = function() {
66053         return -1;
66054     };
66055
66056
66057     category.name = function() {
66058         return t('presets.categories.' + id + '.name', {'default': id});
66059     };
66060
66061
66062     category.terms = function() {
66063         return [];
66064     };
66065
66066
66067     return category;
66068 }
66069
66070 function presetField(id, field) {
66071     field = lodash.clone(field);
66072
66073     field.id = id;
66074
66075
66076     field.matchGeometry = function(geometry) {
66077         return !field.geometry || field.geometry === geometry;
66078     };
66079
66080
66081     field.t = function(scope, options) {
66082         return t('presets.fields.' + id + '.' + scope, options);
66083     };
66084
66085
66086     field.label = function() {
66087         return field.t('label', {'default': id});
66088     };
66089
66090
66091     var placeholder = field.placeholder;
66092     field.placeholder = function() {
66093         return field.t('placeholder', {'default': placeholder});
66094     };
66095
66096
66097     return field;
66098 }
66099
66100 function presetPreset(id, preset, fields) {
66101     preset = lodash.clone(preset);
66102
66103     preset.id = id;
66104     preset.fields = (preset.fields || []).map(getFields);
66105     preset.geometry = (preset.geometry || []);
66106
66107
66108     function getFields(f) {
66109         return fields[f];
66110     }
66111
66112
66113     preset.matchGeometry = function(geometry) {
66114         return preset.geometry.indexOf(geometry) >= 0;
66115     };
66116
66117
66118     var matchScore = preset.matchScore || 1;
66119     preset.matchScore = function(entity) {
66120         var tags = preset.tags,
66121             score = 0;
66122
66123         for (var t$$1 in tags) {
66124             if (entity.tags[t$$1] === tags[t$$1]) {
66125                 score += matchScore;
66126             } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
66127                 score += matchScore / 2;
66128             } else {
66129                 return -1;
66130             }
66131         }
66132
66133         return score;
66134     };
66135
66136
66137     preset.t = function(scope, options) {
66138         return t('presets.presets.' + id + '.' + scope, options);
66139     };
66140
66141
66142     var name = preset.name || '';
66143     preset.name = function() {
66144         if (preset.suggestion) {
66145             id = id.split('/');
66146             id = id[0] + '/' + id[1];
66147             return name + ' - ' + t('presets.presets.' + id + '.name');
66148         }
66149         return preset.t('name', {'default': name});
66150     };
66151
66152
66153     preset.terms = function() {
66154         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
66155     };
66156
66157
66158     preset.isFallback = function() {
66159         var tagCount = Object.keys(preset.tags).length;
66160         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
66161     };
66162
66163
66164     preset.reference = function(geometry) {
66165         var key = Object.keys(preset.tags)[0],
66166             value = preset.tags[key];
66167
66168         if (geometry === 'relation' && key === 'type') {
66169             if (value in preset.tags) {
66170                 key = value;
66171                 value = preset.tags[key];
66172             } else {
66173                 return { rtype: value };
66174             }
66175         }
66176
66177         if (value === '*') {
66178             return { key: key };
66179         } else {
66180             return { key: key, value: value };
66181         }
66182     };
66183
66184
66185     var removeTags = preset.removeTags || preset.tags;
66186     preset.removeTags = function(tags, geometry) {
66187         tags = lodash.omit(tags, lodash.keys(removeTags));
66188
66189         for (var f in preset.fields) {
66190             var field = preset.fields[f];
66191             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
66192                 delete tags[field.key];
66193             }
66194         }
66195
66196         delete tags.area;
66197         return tags;
66198     };
66199
66200
66201     var applyTags = preset.addTags || preset.tags;
66202     preset.applyTags = function(tags, geometry) {
66203         var k;
66204
66205         tags = lodash.clone(tags);
66206
66207         for (k in applyTags) {
66208             if (applyTags[k] === '*') {
66209                 tags[k] = 'yes';
66210             } else {
66211                 tags[k] = applyTags[k];
66212             }
66213         }
66214
66215         // Add area=yes if necessary.
66216         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
66217         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
66218         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
66219         if (geometry === 'area') {
66220             var needsAreaTag = true;
66221             if (preset.geometry.indexOf('line') === -1) {
66222                 for (k in applyTags) {
66223                     if (k in areaKeys) {
66224                         needsAreaTag = false;
66225                         break;
66226                     }
66227                 }
66228             }
66229             if (needsAreaTag) {
66230                 tags.area = 'yes';
66231             }
66232         }
66233
66234         for (var f in preset.fields) {
66235             var field = preset.fields[f];
66236             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
66237                 tags[field.key] = field.default;
66238             }
66239         }
66240
66241         return tags;
66242     };
66243
66244
66245     return preset;
66246 }
66247
66248 function presetIndex() {
66249     // a presetCollection with methods for
66250     // loading new data and returning defaults
66251
66252     var all = presetCollection([]),
66253         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
66254         fields = {},
66255         universal = [],
66256         recent = presetCollection([]);
66257
66258     // Index of presets by (geometry, tag key).
66259     var index = {
66260         point: {},
66261         vertex: {},
66262         line: {},
66263         area: {},
66264         relation: {}
66265     };
66266
66267     all.match = function(entity, resolver) {
66268         var geometry = entity.geometry(resolver);
66269
66270         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
66271         if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
66272             geometry = 'point';
66273         }
66274
66275         var geometryMatches = index[geometry],
66276             best = -1,
66277             match;
66278
66279         for (var k in entity.tags) {
66280             var keyMatches = geometryMatches[k];
66281             if (!keyMatches) continue;
66282
66283             for (var i = 0; i < keyMatches.length; i++) {
66284                 var score = keyMatches[i].matchScore(entity);
66285                 if (score > best) {
66286                     best = score;
66287                     match = keyMatches[i];
66288                 }
66289             }
66290         }
66291
66292         return match || all.item(geometry);
66293     };
66294
66295
66296     // Because of the open nature of tagging, iD will never have a complete
66297     // list of tags used in OSM, so we want it to have logic like "assume
66298     // that a closed way with an amenity tag is an area, unless the amenity
66299     // is one of these specific types". This function computes a structure
66300     // that allows testing of such conditions, based on the presets designated
66301     // as as supporting (or not supporting) the area geometry.
66302     //
66303     // The returned object L is a whitelist/blacklist of tags. A closed way
66304     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
66305     // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
66306     // and the subkeys form the blacklist.
66307     all.areaKeys = function() {
66308         var areaKeys = {},
66309             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
66310             presets = lodash.reject(all.collection, 'suggestion');
66311
66312         // whitelist
66313         presets.forEach(function(d) {
66314             for (var key in d.tags) break;
66315             if (!key) return;
66316             if (ignore.indexOf(key) !== -1) return;
66317
66318             if (d.geometry.indexOf('area') !== -1) {
66319                 areaKeys[key] = areaKeys[key] || {};
66320             }
66321         });
66322
66323         // blacklist
66324         presets.forEach(function(d) {
66325             for (var key in d.tags) break;
66326             if (!key) return;
66327             if (ignore.indexOf(key) !== -1) return;
66328
66329             var value = d.tags[key];
66330             if (d.geometry.indexOf('area') === -1 &&
66331                 d.geometry.indexOf('line') !== -1 &&
66332                 key in areaKeys && value !== '*') {
66333                 areaKeys[key][value] = true;
66334             }
66335         });
66336
66337         return areaKeys;
66338     };
66339
66340
66341     all.init = function() {
66342         var d = data.presets;
66343
66344         if (d.fields) {
66345             lodash.forEach(d.fields, function(d, id) {
66346                 fields[id] = presetField(id, d);
66347                 if (d.universal) universal.push(fields[id]);
66348             });
66349         }
66350
66351         if (d.presets) {
66352             lodash.forEach(d.presets, function(d, id) {
66353                 all.collection.push(presetPreset(id, d, fields));
66354             });
66355         }
66356
66357         if (d.categories) {
66358             lodash.forEach(d.categories, function(d, id) {
66359                 all.collection.push(presetCategory(id, d, all));
66360             });
66361         }
66362
66363         if (d.defaults) {
66364             var getItem = lodash.bind(all.item, all);
66365             defaults = {
66366                 area: presetCollection(d.defaults.area.map(getItem)),
66367                 line: presetCollection(d.defaults.line.map(getItem)),
66368                 point: presetCollection(d.defaults.point.map(getItem)),
66369                 vertex: presetCollection(d.defaults.vertex.map(getItem)),
66370                 relation: presetCollection(d.defaults.relation.map(getItem))
66371             };
66372         }
66373
66374         for (var i = 0; i < all.collection.length; i++) {
66375             var preset = all.collection[i],
66376                 geometry = preset.geometry;
66377
66378             for (var j = 0; j < geometry.length; j++) {
66379                 var g = index[geometry[j]];
66380                 for (var k in preset.tags) {
66381                     (g[k] = g[k] || []).push(preset);
66382                 }
66383             }
66384         }
66385
66386         return all;
66387     };
66388
66389     all.field = function(id) {
66390         return fields[id];
66391     };
66392
66393     all.universal = function() {
66394         return universal;
66395     };
66396
66397     all.defaults = function(geometry, n) {
66398         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
66399             def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
66400         return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
66401     };
66402
66403     all.choose = function(preset) {
66404         if (!preset.isFallback()) {
66405             recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
66406         }
66407         return all;
66408     };
66409
66410     return all;
66411 }
66412
66413 var areaKeys = {};
66414
66415 function setAreaKeys(value) {
66416     areaKeys = value;
66417 }
66418
66419
66420 function coreContext() {
66421     addTranslation('en', en);
66422     setLocale('en');
66423
66424     var dispatch$$1 = dispatch('enter', 'exit', 'change'),
66425         context = {};
66426
66427     // https://github.com/openstreetmap/iD/issues/772
66428     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
66429     var storage;
66430     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
66431     storage = storage || (function() {
66432         var s = {};
66433         return {
66434             getItem: function(k) { return s[k]; },
66435             setItem: function(k, v) { s[k] = v; },
66436             removeItem: function(k) { delete s[k]; }
66437         };
66438     })();
66439
66440     context.storage = function(k, v) {
66441         try {
66442             if (arguments.length === 1) return storage.getItem(k);
66443             else if (v === null) storage.removeItem(k);
66444             else storage.setItem(k, v);
66445         } catch (e) {
66446             // localstorage quota exceeded
66447             /* eslint-disable no-console */
66448             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
66449             /* eslint-enable no-console */
66450         }
66451     };
66452
66453
66454     /* Straight accessors. Avoid using these if you can. */
66455     var ui, connection, history;
66456     context.ui = function() { return ui; };
66457     context.connection = function() { return connection; };
66458     context.history = function() { return history; };
66459
66460
66461     /* Connection */
66462     function entitiesLoaded(err, result) {
66463         if (!err) history.merge(result.data, result.extent);
66464     }
66465
66466     context.preauth = function(options) {
66467         connection.switch(options);
66468         return context;
66469     };
66470
66471     context.loadTiles = function(projection, dimensions, callback) {
66472         function done(err, result) {
66473             entitiesLoaded(err, result);
66474             if (callback) callback(err, result);
66475         }
66476         connection.loadTiles(projection, dimensions, done);
66477     };
66478
66479     context.loadEntity = function(id, callback) {
66480         function done(err, result) {
66481             entitiesLoaded(err, result);
66482             if (callback) callback(err, result);
66483         }
66484         connection.loadEntity(id, done);
66485     };
66486
66487     context.zoomToEntity = function(id, zoomTo) {
66488         if (zoomTo !== false) {
66489             this.loadEntity(id, function(err, result) {
66490                 if (err) return;
66491                 var entity = lodash.find(result.data, function(e) { return e.id === id; });
66492                 if (entity) { map$$1.zoomTo(entity); }
66493             });
66494         }
66495
66496         map$$1.on('drawn.zoomToEntity', function() {
66497             if (!context.hasEntity(id)) return;
66498             map$$1.on('drawn.zoomToEntity', null);
66499             context.on('enter.zoomToEntity', null);
66500             context.enter(modeSelect(context, [id]));
66501         });
66502
66503         context.on('enter.zoomToEntity', function() {
66504             if (mode.id !== 'browse') {
66505                 map$$1.on('drawn.zoomToEntity', null);
66506                 context.on('enter.zoomToEntity', null);
66507             }
66508         });
66509     };
66510
66511     var minEditableZoom = 16;
66512     context.minEditableZoom = function(_) {
66513         if (!arguments.length) return minEditableZoom;
66514         minEditableZoom = _;
66515         connection.tileZoom(_);
66516         return context;
66517     };
66518
66519
66520     /* History */
66521     var inIntro = false;
66522     context.inIntro = function(_) {
66523         if (!arguments.length) return inIntro;
66524         inIntro = _;
66525         return context;
66526     };
66527
66528     context.save = function() {
66529         if (inIntro || (mode && mode.id === 'save') || select('.modal').size()) return;
66530         history.save();
66531         if (history.hasChanges()) return t('save.unsaved_changes');
66532     };
66533
66534
66535     /* Graph */
66536     context.hasEntity = function(id) {
66537         return history.graph().hasEntity(id);
66538     };
66539     context.entity = function(id) {
66540         return history.graph().entity(id);
66541     };
66542     context.childNodes = function(way) {
66543         return history.graph().childNodes(way);
66544     };
66545     context.geometry = function(id) {
66546         return context.entity(id).geometry(history.graph());
66547     };
66548
66549
66550     /* Modes */
66551     var mode;
66552     context.mode = function() {
66553         return mode;
66554     };
66555     context.enter = function(newMode) {
66556         if (mode) {
66557             mode.exit();
66558             dispatch$$1.call('exit', this, mode);
66559         }
66560
66561         mode = newMode;
66562         mode.enter();
66563         dispatch$$1.call('enter', this, mode);
66564     };
66565
66566     context.selectedIDs = function() {
66567         if (mode && mode.selectedIDs) {
66568             return mode.selectedIDs();
66569         } else {
66570             return [];
66571         }
66572     };
66573
66574
66575     /* Behaviors */
66576     context.install = function(behavior) {
66577         context.surface().call(behavior);
66578     };
66579     context.uninstall = function(behavior) {
66580         context.surface().call(behavior.off);
66581     };
66582
66583
66584     /* Copy/Paste */
66585     var copyIDs = [], copyGraph;
66586     context.copyGraph = function() { return copyGraph; };
66587     context.copyIDs = function(_) {
66588         if (!arguments.length) return copyIDs;
66589         copyIDs = _;
66590         copyGraph = history.graph();
66591         return context;
66592     };
66593
66594
66595     /* Background */
66596     var background;
66597     context.background = function() { return background; };
66598
66599
66600     /* Features */
66601     var features;
66602     context.features = function() { return features; };
66603     context.hasHiddenConnections = function(id) {
66604         var graph = history.graph(),
66605             entity = graph.entity(id);
66606         return features.hasHiddenConnections(entity, graph);
66607     };
66608
66609
66610     /* Presets */
66611     var presets;
66612     context.presets = function() { return presets; };
66613
66614
66615     /* Map */
66616     var map$$1;
66617     context.map = function() { return map$$1; };
66618     context.layers = function() { return map$$1.layers; };
66619     context.surface = function() { return map$$1.surface; };
66620     context.editable = function() { return map$$1.editable(); };
66621
66622     context.surfaceRect = function() {
66623         // Work around a bug in Firefox.
66624         //   http://stackoverflow.com/questions/18153989/
66625         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
66626         return context.surface().node().parentNode.getBoundingClientRect();
66627     };
66628
66629
66630     /* Debug */
66631     var debugFlags = {
66632         tile: false,
66633         collision: false,
66634         imagery: false,
66635         imperial: false,
66636         driveLeft: false
66637     };
66638     context.debugFlags = function() {
66639         return debugFlags;
66640     };
66641     context.setDebug = function(flag, val) {
66642         if (arguments.length === 1) val = true;
66643         debugFlags[flag] = val;
66644         dispatch$$1.call('change');
66645         return context;
66646     };
66647     context.getDebug = function(flag) {
66648         return flag && debugFlags[flag];
66649     };
66650
66651
66652     /* Container */
66653     var container, embed;
66654     context.container = function(_) {
66655         if (!arguments.length) return container;
66656         container = _;
66657         container.classed('id-container', true);
66658         return context;
66659     };
66660     context.embed = function(_) {
66661         if (!arguments.length) return embed;
66662         embed = _;
66663         return context;
66664     };
66665
66666
66667     /* Assets */
66668     var assetPath = '';
66669     context.assetPath = function(_) {
66670         if (!arguments.length) return assetPath;
66671         assetPath = _;
66672         return context;
66673     };
66674
66675     var assetMap = {};
66676     context.assetMap = function(_) {
66677         if (!arguments.length) return assetMap;
66678         assetMap = _;
66679         return context;
66680     };
66681
66682     context.asset = function(_) {
66683         var filename = assetPath + _;
66684         return assetMap[filename] || filename;
66685     };
66686
66687     context.imagePath = function(_) {
66688         return context.asset('img/' + _);
66689     };
66690
66691
66692     /* locales */
66693     // `locale` variable contains a "requested locale".
66694     // It won't become the `currentLocale` until after loadLocale() is called.
66695     var locale, localePath;
66696
66697     context.locale = function(loc, path$$1) {
66698         if (!arguments.length) return currentLocale;
66699         locale = loc;
66700         localePath = path$$1;
66701         return context;
66702     };
66703
66704     context.loadLocale = function(callback) {
66705         if (locale && locale !== 'en' && dataLocales.indexOf(locale) !== -1) {
66706             localePath = localePath || context.asset('locales/' + locale + '.json');
66707             json(localePath, function(err, result) {
66708                 if (!err) {
66709                     addTranslation(locale, result[locale]);
66710                     setLocale(locale);
66711                     utilDetect(true);
66712                 }
66713                 if (callback) {
66714                     callback(err);
66715                 }
66716             });
66717         } else {
66718             if (locale) {
66719                 setLocale(locale);
66720                 utilDetect(true);
66721             }
66722             if (callback) {
66723                 callback();
66724             }
66725         }
66726     };
66727
66728
66729     /* reset (aka flush) */
66730     context.reset = context.flush = function() {
66731         context.debouncedSave.cancel();
66732         lodash.each(services, function(service) {
66733             if (service && typeof service.reset === 'function') {
66734                 service.reset(context);
66735             }
66736         });
66737         features.reset();
66738         history.reset();
66739         return context;
66740     };
66741
66742
66743     /* Init */
66744     context.version = '2.0.1';
66745
66746     context.projection = geoRawMercator();
66747
66748     locale = utilDetect().locale;
66749     if (locale && dataLocales.indexOf(locale) === -1) {
66750         locale = locale.split('-')[0];
66751     }
66752
66753     history = coreHistory(context);
66754     context.graph = history.graph;
66755     context.changes = history.changes;
66756     context.intersects = history.intersects;
66757
66758     // Debounce save, since it's a synchronous localStorage write,
66759     // and history changes can happen frequently (e.g. when dragging).
66760     context.debouncedSave = lodash.debounce(context.save, 350);
66761     function withDebouncedSave(fn) {
66762         return function() {
66763             var result = fn.apply(history, arguments);
66764             context.debouncedSave();
66765             return result;
66766         };
66767     }
66768
66769     context.perform = withDebouncedSave(history.perform);
66770     context.replace = withDebouncedSave(history.replace);
66771     context.pop = withDebouncedSave(history.pop);
66772     context.overwrite = withDebouncedSave(history.overwrite);
66773     context.undo = withDebouncedSave(history.undo);
66774     context.redo = withDebouncedSave(history.redo);
66775
66776     ui = uiInit(context);
66777
66778     connection = services.osm;
66779
66780     background = rendererBackground(context);
66781     features = rendererFeatures(context);
66782     presets = presetIndex();
66783
66784     map$$1 = rendererMap(context);
66785     context.mouse = map$$1.mouse;
66786     context.extent = map$$1.extent;
66787     context.pan = map$$1.pan;
66788     context.zoomIn = map$$1.zoomIn;
66789     context.zoomOut = map$$1.zoomOut;
66790     context.zoomInFurther = map$$1.zoomInFurther;
66791     context.zoomOutFurther = map$$1.zoomOutFurther;
66792     context.redrawEnable = map$$1.redrawEnable;
66793
66794     background.init();
66795     presets.init();
66796     areaKeys = presets.areaKeys();
66797
66798     lodash.each(services, function(service) {
66799         if (service && typeof service.init === 'function') {
66800             service.init(context);
66801         }
66802     });
66803
66804
66805     return utilRebind(context, dispatch$$1, 'on');
66806 }
66807
66808 function osmWay() {
66809     if (!(this instanceof osmWay)) {
66810         return (new osmWay()).initialize(arguments);
66811     } else if (arguments.length) {
66812         this.initialize(arguments);
66813     }
66814 }
66815
66816
66817 osmEntity$$1.way = osmWay;
66818
66819 osmWay.prototype = Object.create(osmEntity$$1.prototype);
66820
66821
66822 lodash.extend(osmWay.prototype, {
66823     type: 'way',
66824     nodes: [],
66825
66826
66827     copy: function(resolver, copies) {
66828         if (copies[this.id])
66829             return copies[this.id];
66830
66831         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
66832
66833         var nodes = this.nodes.map(function(id) {
66834             return resolver.entity(id).copy(resolver, copies).id;
66835         });
66836
66837         copy = copy.update({ nodes: nodes });
66838         copies[this.id] = copy;
66839
66840         return copy;
66841     },
66842
66843
66844     extent: function(resolver) {
66845         return resolver.transient(this, 'extent', function() {
66846             var extent$$1 = geoExtent$$1();
66847             for (var i = 0; i < this.nodes.length; i++) {
66848                 var node = resolver.hasEntity(this.nodes[i]);
66849                 if (node) {
66850                     extent$$1._extend(node.extent());
66851                 }
66852             }
66853             return extent$$1;
66854         });
66855     },
66856
66857
66858     first: function() {
66859         return this.nodes[0];
66860     },
66861
66862
66863     last: function() {
66864         return this.nodes[this.nodes.length - 1];
66865     },
66866
66867
66868     contains: function(node) {
66869         return this.nodes.indexOf(node) >= 0;
66870     },
66871
66872
66873     affix: function(node) {
66874         if (this.nodes[0] === node) return 'prefix';
66875         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
66876     },
66877
66878
66879     layer: function() {
66880         // explicit layer tag, clamp between -10, 10..
66881         if (isFinite(this.tags.layer)) {
66882             return Math.max(-10, Math.min(+(this.tags.layer), 10));
66883         }
66884
66885         // implied layer tag..
66886         if (this.tags.location === 'overground') return 1;
66887         if (this.tags.location === 'underground') return -1;
66888         if (this.tags.location === 'underwater') return -10;
66889
66890         if (this.tags.power === 'line') return 10;
66891         if (this.tags.power === 'minor_line') return 10;
66892         if (this.tags.aerialway) return 10;
66893         if (this.tags.bridge) return 1;
66894         if (this.tags.cutting) return -1;
66895         if (this.tags.tunnel) return -1;
66896         if (this.tags.waterway) return -1;
66897         if (this.tags.man_made === 'pipeline') return -10;
66898         if (this.tags.boundary) return -10;
66899         return 0;
66900     },
66901
66902
66903     isOneWay: function() {
66904         // explicit oneway tag..
66905         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
66906         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
66907
66908         // implied oneway tag..
66909         for (var key in this.tags) {
66910             if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
66911                 return true;
66912         }
66913         return false;
66914     },
66915
66916
66917     lanes: function() {
66918         return osmLanes(this);
66919     },
66920
66921
66922     isClosed: function() {
66923         return this.nodes.length > 0 && this.first() === this.last();
66924     },
66925
66926
66927     isConvex: function(resolver) {
66928         if (!this.isClosed() || this.isDegenerate()) return null;
66929
66930         var nodes = lodash.uniq(resolver.childNodes(this)),
66931             coords = lodash.map(nodes, 'loc'),
66932             curr = 0, prev = 0;
66933
66934         for (var i = 0; i < coords.length; i++) {
66935             var o = coords[(i+1) % coords.length],
66936                 a = coords[i],
66937                 b = coords[(i+2) % coords.length],
66938                 res = geoCross(o, a, b);
66939
66940             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
66941             if (curr === 0) {
66942                 continue;
66943             } else if (prev && curr !== prev) {
66944                 return false;
66945             }
66946             prev = curr;
66947         }
66948         return true;
66949     },
66950
66951
66952     isArea: function() {
66953         if (this.tags.area === 'yes')
66954             return true;
66955         if (!this.isClosed() || this.tags.area === 'no')
66956             return false;
66957         for (var key in this.tags) {
66958             if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
66959                 return true;
66960             }
66961         }
66962         return false;
66963     },
66964
66965
66966     isDegenerate: function() {
66967         return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
66968     },
66969
66970
66971     areAdjacent: function(n1, n2) {
66972         for (var i = 0; i < this.nodes.length; i++) {
66973             if (this.nodes[i] === n1) {
66974                 if (this.nodes[i - 1] === n2) return true;
66975                 if (this.nodes[i + 1] === n2) return true;
66976             }
66977         }
66978         return false;
66979     },
66980
66981
66982     geometry: function(graph) {
66983         return graph.transient(this, 'geometry', function() {
66984             return this.isArea() ? 'area' : 'line';
66985         });
66986     },
66987
66988
66989     addNode: function(id, index) {
66990         var nodes = this.nodes.slice();
66991         nodes.splice(index === undefined ? nodes.length : index, 0, id);
66992         return this.update({nodes: nodes});
66993     },
66994
66995
66996     updateNode: function(id, index) {
66997         var nodes = this.nodes.slice();
66998         nodes.splice(index, 1, id);
66999         return this.update({nodes: nodes});
67000     },
67001
67002
67003     replaceNode: function(needle, replacement) {
67004         if (this.nodes.indexOf(needle) < 0)
67005             return this;
67006
67007         var nodes = this.nodes.slice();
67008         for (var i = 0; i < nodes.length; i++) {
67009             if (nodes[i] === needle) {
67010                 nodes[i] = replacement;
67011             }
67012         }
67013         return this.update({nodes: nodes});
67014     },
67015
67016
67017     removeNode: function(id) {
67018         var nodes = [];
67019
67020         for (var i = 0; i < this.nodes.length; i++) {
67021             var node = this.nodes[i];
67022             if (node !== id && nodes[nodes.length - 1] !== node) {
67023                 nodes.push(node);
67024             }
67025         }
67026
67027         // Preserve circularity
67028         if (this.nodes.length > 1 && this.first() === id && this.last() === id && nodes[nodes.length - 1] !== nodes[0]) {
67029             nodes.push(nodes[0]);
67030         }
67031
67032         return this.update({nodes: nodes});
67033     },
67034
67035
67036     asJXON: function(changeset_id) {
67037         var r = {
67038             way: {
67039                 '@id': this.osmId(),
67040                 '@version': this.version || 0,
67041                 nd: lodash.map(this.nodes, function(id) {
67042                     return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
67043                 }),
67044                 tag: lodash.map(this.tags, function(v, k) {
67045                     return { keyAttributes: { k: k, v: v } };
67046                 })
67047             }
67048         };
67049         if (changeset_id) r.way['@changeset'] = changeset_id;
67050         return r;
67051     },
67052
67053
67054     asGeoJSON: function(resolver) {
67055         return resolver.transient(this, 'GeoJSON', function() {
67056             var coordinates = lodash.map(resolver.childNodes(this), 'loc');
67057             if (this.isArea() && this.isClosed()) {
67058                 return {
67059                     type: 'Polygon',
67060                     coordinates: [coordinates]
67061                 };
67062             } else {
67063                 return {
67064                     type: 'LineString',
67065                     coordinates: coordinates
67066                 };
67067             }
67068         });
67069     },
67070
67071
67072     area: function(resolver) {
67073         return resolver.transient(this, 'area', function() {
67074             var nodes = resolver.childNodes(this);
67075
67076             var json$$1 = {
67077                 type: 'Polygon',
67078                 coordinates: [lodash.map(nodes, 'loc')]
67079             };
67080
67081             if (!this.isClosed() && nodes.length) {
67082                 json$$1.coordinates[0].push(nodes[0].loc);
67083             }
67084
67085             var area$$1 = area$1(json$$1);
67086
67087             // Heuristic for detecting counterclockwise winding order. Assumes
67088             // that OpenStreetMap polygons are not hemisphere-spanning.
67089             if (area$$1 > 2 * Math.PI) {
67090                 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
67091                 area$$1 = area$1(json$$1);
67092             }
67093
67094             return isNaN(area$$1) ? 0 : area$$1;
67095         });
67096     }
67097 });
67098
67099 function osmTurn(turn) {
67100     if (!(this instanceof osmTurn))
67101         return new osmTurn(turn);
67102     lodash.extend(this, turn);
67103 }
67104
67105
67106 function osmIntersection(graph, vertexId) {
67107     var vertex = graph.entity(vertexId),
67108         parentWays = graph.parentWays(vertex),
67109         coincident = [],
67110         highways = {};
67111
67112     function addHighway(way, adjacentNodeId) {
67113         if (highways[adjacentNodeId]) {
67114             coincident.push(adjacentNodeId);
67115         } else {
67116             highways[adjacentNodeId] = way;
67117         }
67118     }
67119
67120     // Pre-split ways that would need to be split in
67121     // order to add a restriction. The real split will
67122     // happen when the restriction is added.
67123     parentWays.forEach(function(way) {
67124         if (!way.tags.highway || way.isArea() || way.isDegenerate())
67125             return;
67126
67127         var isFirst = (vertexId === way.first()),
67128             isLast = (vertexId === way.last()),
67129             isAffix = (isFirst || isLast),
67130             isClosingNode = (isFirst && isLast);
67131
67132         if (isAffix && !isClosingNode) {
67133             var index = (isFirst ? 1 : way.nodes.length - 2);
67134             addHighway(way, way.nodes[index]);
67135
67136         } else {
67137             var splitIndex, wayA, wayB, indexA, indexB;
67138             if (isClosingNode) {
67139                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
67140                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
67141                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
67142                 indexA = 1;
67143                 indexB = way.nodes.length - 2;
67144             } else {
67145                 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
67146                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
67147                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
67148                 indexA = splitIndex - 1;
67149                 indexB = splitIndex + 1;
67150             }
67151             graph = graph.replace(wayA).replace(wayB);
67152             addHighway(wayA, way.nodes[indexA]);
67153             addHighway(wayB, way.nodes[indexB]);
67154         }
67155     });
67156
67157     // remove any ways from this intersection that are coincident
67158     // (i.e. any adjacent node used by more than one intersecting way)
67159     coincident.forEach(function (n) {
67160         delete highways[n];
67161     });
67162
67163
67164     var intersection = {
67165         highways: highways,
67166         ways: lodash.values(highways),
67167         graph: graph
67168     };
67169
67170
67171     intersection.adjacentNodeId = function(fromWayId) {
67172         return lodash.find(lodash.keys(highways), function(k) {
67173             return highways[k].id === fromWayId;
67174         });
67175     };
67176
67177
67178     intersection.turns = function(fromNodeId) {
67179         var start = highways[fromNodeId];
67180         if (!start)
67181             return [];
67182
67183         if (start.first() === vertex.id && start.tags.oneway === 'yes')
67184             return [];
67185         if (start.last() === vertex.id && start.tags.oneway === '-1')
67186             return [];
67187
67188         function withRestriction(turn) {
67189             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
67190                 if (relation.tags.type !== 'restriction')
67191                     return;
67192
67193                 var f = relation.memberByRole('from'),
67194                     t = relation.memberByRole('to'),
67195                     v = relation.memberByRole('via');
67196
67197                 if (f && f.id === turn.from.way &&
67198                     v && v.id === turn.via.node &&
67199                     t && t.id === turn.to.way) {
67200                     turn.restriction = relation.id;
67201                 } else if (/^only_/.test(relation.tags.restriction) &&
67202                     f && f.id === turn.from.way &&
67203                     v && v.id === turn.via.node &&
67204                     t && t.id !== turn.to.way) {
67205                     turn.restriction = relation.id;
67206                     turn.indirect_restriction = true;
67207                 }
67208             });
67209
67210             return osmTurn(turn);
67211         }
67212
67213
67214         var from = {
67215                 node: fromNodeId,
67216                 way: start.id.split(/-(a|b)/)[0]
67217             },
67218             via = { node: vertex.id },
67219             turns = [];
67220
67221         lodash.each(highways, function(end, adjacentNodeId) {
67222             if (end === start)
67223                 return;
67224
67225             // backward
67226             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
67227                 turns.push(withRestriction({
67228                     from: from,
67229                     via: via,
67230                     to: {
67231                         node: adjacentNodeId,
67232                         way: end.id.split(/-(a|b)/)[0]
67233                     }
67234                 }));
67235             }
67236
67237             // forward
67238             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
67239                 turns.push(withRestriction({
67240                     from: from,
67241                     via: via,
67242                     to: {
67243                         node: adjacentNodeId,
67244                         way: end.id.split(/-(a|b)/)[0]
67245                     }
67246                 }));
67247             }
67248
67249         });
67250
67251         // U-turn
67252         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
67253             turns.push(withRestriction({
67254                 from: from,
67255                 via: via,
67256                 to: from,
67257                 u: true
67258             }));
67259         }
67260
67261         return turns;
67262     };
67263
67264     return intersection;
67265 }
67266
67267
67268 function osmInferRestriction(graph, from, via, to, projection) {
67269     var fromWay = graph.entity(from.way),
67270         fromNode = graph.entity(from.node),
67271         toWay = graph.entity(to.way),
67272         toNode = graph.entity(to.node),
67273         viaNode = graph.entity(via.node),
67274         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
67275             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
67276         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
67277             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
67278         angle = geoAngle(viaNode, fromNode, projection) -
67279                 geoAngle(viaNode, toNode, projection);
67280
67281     angle = angle * 180 / Math.PI;
67282
67283     while (angle < 0)
67284         angle += 360;
67285
67286     if (fromNode === toNode)
67287         return 'no_u_turn';
67288     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
67289         return 'no_u_turn';
67290     if (angle < 158)
67291         return 'no_right_turn';
67292     if (angle > 202)
67293         return 'no_left_turn';
67294
67295     return 'no_straight_on';
67296 }
67297
67298 function actionAddMember(relationId, member, memberIndex) {
67299     return function(graph) {
67300         var relation = graph.entity(relationId);
67301
67302         if (isNaN(memberIndex) && member.type === 'way') {
67303             var members = relation.indexedMembers();
67304             members.push(member);
67305
67306             var joined = osmJoinWays(members, graph);
67307             for (var i = 0; i < joined.length; i++) {
67308                 var segment = joined[i];
67309                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
67310                     if (segment[j] !== member)
67311                         continue;
67312
67313                     if (j === 0) {
67314                         memberIndex = segment[j + 1].index;
67315                     } else if (j === segment.length - 1) {
67316                         memberIndex = segment[j - 1].index + 1;
67317                     } else {
67318                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
67319                     }
67320                 }
67321             }
67322         }
67323
67324         return graph.replace(relation.addMember(member, memberIndex));
67325     };
67326 }
67327
67328 function actionAddMidpoint(midpoint, node) {
67329     return function(graph) {
67330         graph = graph.replace(node.move(midpoint.loc));
67331
67332         var parents = lodash.intersection(
67333             graph.parentWays(graph.entity(midpoint.edge[0])),
67334             graph.parentWays(graph.entity(midpoint.edge[1])));
67335
67336         parents.forEach(function(way) {
67337             for (var i = 0; i < way.nodes.length - 1; i++) {
67338                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
67339                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
67340
67341                     // Add only one midpoint on doubled-back segments,
67342                     // turning them into self-intersections.
67343                     return;
67344                 }
67345             }
67346         });
67347
67348         return graph;
67349     };
67350 }
67351
67352 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
67353 function actionAddVertex(wayId, nodeId, index) {
67354     return function(graph) {
67355         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
67356     };
67357 }
67358
67359 function actionChangeMember(relationId, member, memberIndex) {
67360     return function(graph) {
67361         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
67362     };
67363 }
67364
67365 function actionChangePreset(entityId, oldPreset, newPreset) {
67366     return function(graph) {
67367         var entity = graph.entity(entityId),
67368             geometry = entity.geometry(graph),
67369             tags = entity.tags;
67370
67371         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
67372         if (newPreset) tags = newPreset.applyTags(tags, geometry);
67373
67374         return graph.replace(entity.update({tags: tags}));
67375     };
67376 }
67377
67378 function actionChangeTags(entityId, tags) {
67379     return function(graph) {
67380         var entity = graph.entity(entityId);
67381         return graph.replace(entity.update({tags: tags}));
67382     };
67383 }
67384
67385 function actionCircularize(wayId, projection, maxAngle) {
67386     maxAngle = (maxAngle || 20) * Math.PI / 180;
67387
67388
67389     var action = function(graph) {
67390         var way = graph.entity(wayId);
67391
67392         if (!way.isConvex(graph)) {
67393             graph = action.makeConvex(graph);
67394         }
67395
67396         var nodes = lodash.uniq(graph.childNodes(way)),
67397             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
67398             points = nodes.map(function(n) { return projection(n.loc); }),
67399             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
67400             centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
67401             radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
67402             sign = d3polygonArea(points) > 0 ? 1 : -1,
67403             ids;
67404
67405         // we need atleast two key nodes for the algorithm to work
67406         if (!keyNodes.length) {
67407             keyNodes = [nodes[0]];
67408             keyPoints = [points[0]];
67409         }
67410
67411         if (keyNodes.length === 1) {
67412             var index = nodes.indexOf(keyNodes[0]),
67413                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
67414
67415             keyNodes.push(nodes[oppositeIndex]);
67416             keyPoints.push(points[oppositeIndex]);
67417         }
67418
67419         // key points and nodes are those connected to the ways,
67420         // they are projected onto the circle, inbetween nodes are moved
67421         // to constant intervals between key nodes, extra inbetween nodes are
67422         // added if necessary.
67423         for (var i = 0; i < keyPoints.length; i++) {
67424             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
67425                 startNode = keyNodes[i],
67426                 endNode = keyNodes[nextKeyNodeIndex],
67427                 startNodeIndex = nodes.indexOf(startNode),
67428                 endNodeIndex = nodes.indexOf(endNode),
67429                 numberNewPoints = -1,
67430                 indexRange = endNodeIndex - startNodeIndex,
67431                 distance, totalAngle, eachAngle, startAngle, endAngle,
67432                 angle, loc, node, j,
67433                 inBetweenNodes = [];
67434
67435             if (indexRange < 0) {
67436                 indexRange += nodes.length;
67437             }
67438
67439             // position this key node
67440             distance = geoEuclideanDistance(centroid, keyPoints[i]);
67441             if (distance === 0) { distance = 1e-4; }
67442             keyPoints[i] = [
67443                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
67444                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
67445             graph = graph.replace(keyNodes[i].move(projection.invert(keyPoints[i])));
67446
67447             // figure out the between delta angle we want to match to
67448             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
67449             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
67450             totalAngle = endAngle - startAngle;
67451
67452             // detects looping around -pi/pi
67453             if (totalAngle * sign > 0) {
67454                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
67455             }
67456
67457             do {
67458                 numberNewPoints++;
67459                 eachAngle = totalAngle / (indexRange + numberNewPoints);
67460             } while (Math.abs(eachAngle) > maxAngle);
67461
67462             // move existing points
67463             for (j = 1; j < indexRange; j++) {
67464                 angle = startAngle + j * eachAngle;
67465                 loc = projection.invert([
67466                     centroid[0] + Math.cos(angle)*radius,
67467                     centroid[1] + Math.sin(angle)*radius]);
67468
67469                 node = nodes[(j + startNodeIndex) % nodes.length].move(loc);
67470                 graph = graph.replace(node);
67471             }
67472
67473             // add new inbetween nodes if necessary
67474             for (j = 0; j < numberNewPoints; j++) {
67475                 angle = startAngle + (indexRange + j) * eachAngle;
67476                 loc = projection.invert([
67477                     centroid[0] + Math.cos(angle) * radius,
67478                     centroid[1] + Math.sin(angle) * radius]);
67479
67480                 node = osmNode({loc: loc});
67481                 graph = graph.replace(node);
67482
67483                 nodes.splice(endNodeIndex + j, 0, node);
67484                 inBetweenNodes.push(node.id);
67485             }
67486
67487             // Check for other ways that share these keyNodes..
67488             // If keyNodes are adjacent in both ways,
67489             // we can add inBetween nodes to that shared way too..
67490             if (indexRange === 1 && inBetweenNodes.length) {
67491                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
67492                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
67493                     wayDirection1 = (endIndex1 - startIndex1);
67494                 if (wayDirection1 < -1) { wayDirection1 = 1; }
67495
67496                 /* eslint-disable no-loop-func */
67497                 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
67498                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
67499                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
67500                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
67501                             wayDirection2 = (endIndex2 - startIndex2),
67502                             insertAt = endIndex2;
67503                         if (wayDirection2 < -1) { wayDirection2 = 1; }
67504
67505                         if (wayDirection1 !== wayDirection2) {
67506                             inBetweenNodes.reverse();
67507                             insertAt = startIndex2;
67508                         }
67509                         for (j = 0; j < inBetweenNodes.length; j++) {
67510                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
67511                         }
67512                         graph = graph.replace(sharedWay);
67513                     }
67514                 });
67515                 /* eslint-enable no-loop-func */
67516             }
67517
67518         }
67519
67520         // update the way to have all the new nodes
67521         ids = nodes.map(function(n) { return n.id; });
67522         ids.push(ids[0]);
67523
67524         way = way.update({nodes: ids});
67525         graph = graph.replace(way);
67526
67527         return graph;
67528     };
67529
67530
67531     action.makeConvex = function(graph) {
67532         var way = graph.entity(wayId),
67533             nodes = lodash.uniq(graph.childNodes(way)),
67534             points = nodes.map(function(n) { return projection(n.loc); }),
67535             sign = d3polygonArea(points) > 0 ? 1 : -1,
67536             hull = d3polygonHull(points);
67537
67538         // D3 convex hulls go counterclockwise..
67539         if (sign === -1) {
67540             nodes.reverse();
67541             points.reverse();
67542         }
67543
67544         for (var i = 0; i < hull.length - 1; i++) {
67545             var startIndex = points.indexOf(hull[i]),
67546                 endIndex = points.indexOf(hull[i+1]),
67547                 indexRange = (endIndex - startIndex);
67548
67549             if (indexRange < 0) {
67550                 indexRange += nodes.length;
67551             }
67552
67553             // move interior nodes to the surface of the convex hull..
67554             for (var j = 1; j < indexRange; j++) {
67555                 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
67556                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
67557                 graph = graph.replace(node);
67558             }
67559         }
67560         return graph;
67561     };
67562
67563
67564     action.disabled = function(graph) {
67565         if (!graph.entity(wayId).isClosed())
67566             return 'not_closed';
67567     };
67568
67569
67570     return action;
67571 }
67572
67573 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
67574 function actionDeleteWay(wayId) {
67575
67576
67577     function canDeleteNode(node, graph) {
67578         return !graph.parentWays(node).length &&
67579             !graph.parentRelations(node).length &&
67580             !node.hasInterestingTags();
67581     }
67582
67583
67584     var action = function(graph) {
67585         var way = graph.entity(wayId);
67586
67587         graph.parentRelations(way)
67588             .forEach(function(parent) {
67589                 parent = parent.removeMembersWithID(wayId);
67590                 graph = graph.replace(parent);
67591
67592                 if (parent.isDegenerate()) {
67593                     graph = actionDeleteRelation(parent.id)(graph);
67594                 }
67595             });
67596
67597         lodash.uniq(way.nodes).forEach(function(nodeId) {
67598             graph = graph.replace(way.removeNode(nodeId));
67599
67600             var node = graph.entity(nodeId);
67601             if (canDeleteNode(node, graph)) {
67602                 graph = graph.remove(node);
67603             }
67604         });
67605
67606         return graph.remove(way);
67607     };
67608
67609
67610     action.disabled = function(graph) {
67611         var disabled = false;
67612
67613         graph.parentRelations(graph.entity(wayId)).forEach(function(parent) {
67614             var type = parent.tags.type,
67615                 role = parent.memberById(wayId).role || 'outer';
67616             if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
67617                 disabled = 'part_of_relation';
67618             }
67619         });
67620
67621         return disabled;
67622     };
67623
67624
67625     return action;
67626 }
67627
67628 function actionDeleteMultiple(ids) {
67629     var actions = {
67630         way: actionDeleteWay,
67631         node: actionDeleteNode,
67632         relation: actionDeleteRelation
67633     };
67634
67635
67636     var action = function(graph) {
67637         ids.forEach(function(id) {
67638             if (graph.hasEntity(id)) { // It may have been deleted aready.
67639                 graph = actions[graph.entity(id).type](id)(graph);
67640             }
67641         });
67642
67643         return graph;
67644     };
67645
67646
67647     action.disabled = function(graph) {
67648         for (var i = 0; i < ids.length; i++) {
67649             var id = ids[i],
67650                 disabled = actions[graph.entity(id).type](id).disabled(graph);
67651             if (disabled) return disabled;
67652         }
67653     };
67654
67655
67656     return action;
67657 }
67658
67659 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
67660 function actionDeleteRelation(relationId) {
67661
67662
67663     function canDeleteEntity(entity, graph) {
67664         return !graph.parentWays(entity).length &&
67665             !graph.parentRelations(entity).length &&
67666             !entity.hasInterestingTags();
67667     }
67668
67669
67670     var action = function(graph) {
67671         var relation = graph.entity(relationId);
67672
67673         graph.parentRelations(relation)
67674             .forEach(function(parent) {
67675                 parent = parent.removeMembersWithID(relationId);
67676                 graph = graph.replace(parent);
67677
67678                 if (parent.isDegenerate()) {
67679                     graph = actionDeleteRelation(parent.id)(graph);
67680                 }
67681             });
67682
67683         lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
67684             graph = graph.replace(relation.removeMembersWithID(memberId));
67685
67686             var entity = graph.entity(memberId);
67687             if (canDeleteEntity(entity, graph)) {
67688                 graph = actionDeleteMultiple([memberId])(graph);
67689             }
67690         });
67691
67692         return graph.remove(relation);
67693     };
67694
67695
67696     action.disabled = function(graph) {
67697         if (!graph.entity(relationId).isComplete(graph))
67698             return 'incomplete_relation';
67699     };
67700
67701
67702     return action;
67703 }
67704
67705 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
67706 function actionDeleteNode(nodeId) {
67707     var action = function(graph) {
67708         var node = graph.entity(nodeId);
67709
67710         graph.parentWays(node)
67711             .forEach(function(parent) {
67712                 parent = parent.removeNode(nodeId);
67713                 graph = graph.replace(parent);
67714
67715                 if (parent.isDegenerate()) {
67716                     graph = actionDeleteWay(parent.id)(graph);
67717                 }
67718             });
67719
67720         graph.parentRelations(node)
67721             .forEach(function(parent) {
67722                 parent = parent.removeMembersWithID(nodeId);
67723                 graph = graph.replace(parent);
67724
67725                 if (parent.isDegenerate()) {
67726                     graph = actionDeleteRelation(parent.id)(graph);
67727                 }
67728             });
67729
67730         return graph.remove(node);
67731     };
67732
67733
67734     action.disabled = function() {
67735         return false;
67736     };
67737
67738
67739     return action;
67740 }
67741
67742 // Connect the ways at the given nodes.
67743 //
67744 // The last node will survive. All other nodes will be replaced with
67745 // the surviving node in parent ways, and then removed.
67746 //
67747 // Tags and relation memberships of of non-surviving nodes are merged
67748 // to the survivor.
67749 //
67750 // This is the inverse of `iD.actionDisconnect`.
67751 //
67752 // Reference:
67753 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
67754 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
67755 //
67756 function actionConnect(nodeIds) {
67757     return function(graph) {
67758         var survivor = graph.entity(lodash.last(nodeIds));
67759
67760         for (var i = 0; i < nodeIds.length - 1; i++) {
67761             var node = graph.entity(nodeIds[i]);
67762
67763             /* eslint-disable no-loop-func */
67764             graph.parentWays(node).forEach(function(parent) {
67765                 if (!parent.areAdjacent(node.id, survivor.id)) {
67766                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
67767                 }
67768             });
67769
67770             graph.parentRelations(node).forEach(function(parent) {
67771                 graph = graph.replace(parent.replaceMember(node, survivor));
67772             });
67773             /* eslint-enable no-loop-func */
67774
67775             survivor = survivor.mergeTags(node.tags);
67776             graph = actionDeleteNode(node.id)(graph);
67777         }
67778
67779         graph = graph.replace(survivor);
67780
67781         return graph;
67782     };
67783 }
67784
67785 function actionCopyEntities(ids, fromGraph) {
67786     var copies = {};
67787
67788
67789     var action = function(graph) {
67790         ids.forEach(function(id) {
67791             fromGraph.entity(id).copy(fromGraph, copies);
67792         });
67793
67794         for (var id in copies) {
67795             graph = graph.replace(copies[id]);
67796         }
67797
67798         return graph;
67799     };
67800
67801
67802     action.copies = function() {
67803         return copies;
67804     };
67805
67806
67807     return action;
67808 }
67809
67810 function actionDeleteMember(relationId, memberIndex) {
67811     return function(graph) {
67812         var relation = graph.entity(relationId)
67813             .removeMember(memberIndex);
67814
67815         graph = graph.replace(relation);
67816
67817         if (relation.isDegenerate())
67818             graph = actionDeleteRelation(relation.id)(graph);
67819
67820         return graph;
67821     };
67822 }
67823
67824 function actionDeprecateTags(entityId) {
67825
67826     return function(graph) {
67827         var entity = graph.entity(entityId),
67828             newtags = lodash.clone(entity.tags),
67829             change = false,
67830             rule;
67831
67832         // This handles dataDeprecated tags with a single condition
67833         for (var i = 0; i < dataDeprecated.length; i++) {
67834
67835             rule = dataDeprecated[i];
67836             var match = lodash.toPairs(rule.old)[0],
67837                 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
67838
67839             if (entity.tags[match[0]] && match[1] === '*') {
67840
67841                 var value = entity.tags[match[0]];
67842                 if (replacements && !newtags[replacements[0][0]]) {
67843                     newtags[replacements[0][0]] = value;
67844                 }
67845                 delete newtags[match[0]];
67846                 change = true;
67847
67848             } else if (entity.tags[match[0]] === match[1]) {
67849                 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
67850                 change = true;
67851             }
67852         }
67853
67854         if (change) {
67855             return graph.replace(entity.update({tags: newtags}));
67856         } else {
67857             return graph;
67858         }
67859     };
67860 }
67861
67862 function actionDiscardTags(difference) {
67863
67864     return function(graph) {
67865         function discardTags(entity) {
67866             if (!lodash.isEmpty(entity.tags)) {
67867                 var tags = {};
67868                 lodash.each(entity.tags, function(v, k) {
67869                     if (v) tags[k] = v;
67870                 });
67871
67872                 graph = graph.replace(entity.update({
67873                     tags: lodash.omit(tags, dataDiscarded)
67874                 }));
67875             }
67876         }
67877
67878         difference.modified().forEach(discardTags);
67879         difference.created().forEach(discardTags);
67880
67881         return graph;
67882     };
67883 }
67884
67885 // Disconect the ways at the given node.
67886 //
67887 // Optionally, disconnect only the given ways.
67888 //
67889 // For testing convenience, accepts an ID to assign to the (first) new node.
67890 // Normally, this will be undefined and the way will automatically
67891 // be assigned a new ID.
67892 //
67893 // This is the inverse of `iD.actionConnect`.
67894 //
67895 // Reference:
67896 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
67897 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
67898 //
67899 function actionDisconnect(nodeId, newNodeId) {
67900     var wayIds;
67901
67902
67903     var action = function(graph) {
67904         var node = graph.entity(nodeId),
67905             connections = action.connections(graph);
67906
67907         connections.forEach(function(connection) {
67908             var way = graph.entity(connection.wayID),
67909                 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
67910
67911             graph = graph.replace(newNode);
67912             if (connection.index === 0 && way.isArea()) {
67913                 // replace shared node with shared node..
67914                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
67915             } else {
67916                 // replace shared node with multiple new nodes..
67917                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
67918             }
67919         });
67920
67921         return graph;
67922     };
67923
67924
67925     action.connections = function(graph) {
67926         var candidates = [],
67927             keeping = false,
67928             parentWays = graph.parentWays(graph.entity(nodeId));
67929
67930         parentWays.forEach(function(way) {
67931             if (wayIds && wayIds.indexOf(way.id) === -1) {
67932                 keeping = true;
67933                 return;
67934             }
67935             if (way.isArea() && (way.nodes[0] === nodeId)) {
67936                 candidates.push({wayID: way.id, index: 0});
67937             } else {
67938                 way.nodes.forEach(function(waynode, index) {
67939                     if (waynode === nodeId) {
67940                         candidates.push({wayID: way.id, index: index});
67941                     }
67942                 });
67943             }
67944         });
67945
67946         return keeping ? candidates : candidates.slice(1);
67947     };
67948
67949
67950     action.disabled = function(graph) {
67951         var connections = action.connections(graph);
67952         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
67953             return 'not_connected';
67954
67955         var parentWays = graph.parentWays(graph.entity(nodeId)),
67956             seenRelationIds = {},
67957             sharedRelation;
67958
67959         parentWays.forEach(function(way) {
67960             if (wayIds && wayIds.indexOf(way.id) === -1)
67961                 return;
67962
67963             var relations = graph.parentRelations(way);
67964             relations.forEach(function(relation) {
67965                 if (relation.id in seenRelationIds) {
67966                     sharedRelation = relation;
67967                 } else {
67968                     seenRelationIds[relation.id] = true;
67969                 }
67970             });
67971         });
67972
67973         if (sharedRelation)
67974             return 'relation';
67975     };
67976
67977
67978     action.limitWays = function(_) {
67979         if (!arguments.length) return wayIds;
67980         wayIds = _;
67981         return action;
67982     };
67983
67984
67985     return action;
67986 }
67987
67988 // Join ways at the end node they share.
67989 //
67990 // This is the inverse of `iD.actionSplit`.
67991 //
67992 // Reference:
67993 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
67994 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
67995 //
67996 function actionJoin(ids) {
67997
67998     function groupEntitiesByGeometry(graph) {
67999         var entities = ids.map(function(id) { return graph.entity(id); });
68000         return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
68001     }
68002
68003
68004     var action = function(graph) {
68005         var ways = ids.map(graph.entity, graph),
68006             survivor = ways[0];
68007
68008         // Prefer to keep an existing way.
68009         for (var i = 0; i < ways.length; i++) {
68010             if (!ways[i].isNew()) {
68011                 survivor = ways[i];
68012                 break;
68013             }
68014         }
68015
68016         var joined = osmJoinWays(ways, graph)[0];
68017
68018         survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
68019         graph = graph.replace(survivor);
68020
68021         joined.forEach(function(way) {
68022             if (way.id === survivor.id)
68023                 return;
68024
68025             graph.parentRelations(way).forEach(function(parent) {
68026                 graph = graph.replace(parent.replaceMember(way, survivor));
68027             });
68028
68029             survivor = survivor.mergeTags(way.tags);
68030
68031             graph = graph.replace(survivor);
68032             graph = actionDeleteWay(way.id)(graph);
68033         });
68034
68035         return graph;
68036     };
68037
68038
68039     action.disabled = function(graph) {
68040         var geometries = groupEntitiesByGeometry(graph);
68041         if (ids.length < 2 || ids.length !== geometries.line.length)
68042             return 'not_eligible';
68043
68044         var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
68045         if (joined.length > 1)
68046             return 'not_adjacent';
68047
68048         var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
68049             relation,
68050             tags = {},
68051             conflicting = false;
68052
68053         joined[0].forEach(function(way) {
68054             var parents = graph.parentRelations(way);
68055             parents.forEach(function(parent) {
68056                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
68057                     relation = parent;
68058             });
68059
68060             for (var k in way.tags) {
68061                 if (!(k in tags)) {
68062                     tags[k] = way.tags[k];
68063                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
68064                     conflicting = true;
68065                 }
68066             }
68067         });
68068
68069         if (relation)
68070             return 'restriction';
68071
68072         if (conflicting)
68073             return 'conflicting_tags';
68074     };
68075
68076
68077     return action;
68078 }
68079
68080 function actionMerge(ids) {
68081
68082     function groupEntitiesByGeometry(graph) {
68083         var entities = ids.map(function(id) { return graph.entity(id); });
68084         return lodash.extend({point: [], area: [], line: [], relation: []},
68085             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
68086     }
68087
68088
68089     var action = function(graph) {
68090         var geometries = groupEntitiesByGeometry(graph),
68091             target = geometries.area[0] || geometries.line[0],
68092             points = geometries.point;
68093
68094         points.forEach(function(point) {
68095             target = target.mergeTags(point.tags);
68096
68097             graph.parentRelations(point).forEach(function(parent) {
68098                 graph = graph.replace(parent.replaceMember(point, target));
68099             });
68100
68101             graph = graph.remove(point);
68102         });
68103
68104         graph = graph.replace(target);
68105
68106         return graph;
68107     };
68108
68109
68110     action.disabled = function(graph) {
68111         var geometries = groupEntitiesByGeometry(graph);
68112         if (geometries.point.length === 0 ||
68113             (geometries.area.length + geometries.line.length) !== 1 ||
68114             geometries.relation.length !== 0)
68115             return 'not_eligible';
68116     };
68117
68118
68119     return action;
68120 }
68121
68122 function actionMergePolygon(ids, newRelationId) {
68123
68124     function groupEntities(graph) {
68125         var entities = ids.map(function (id) { return graph.entity(id); });
68126         return lodash.extend({
68127                 closedWay: [],
68128                 multipolygon: [],
68129                 other: []
68130             }, lodash.groupBy(entities, function(entity) {
68131                 if (entity.type === 'way' && entity.isClosed()) {
68132                     return 'closedWay';
68133                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
68134                     return 'multipolygon';
68135                 } else {
68136                     return 'other';
68137                 }
68138             }));
68139     }
68140
68141
68142     var action = function(graph) {
68143         var entities = groupEntities(graph);
68144
68145         // An array representing all the polygons that are part of the multipolygon.
68146         //
68147         // Each element is itself an array of objects with an id property, and has a
68148         // locs property which is an array of the locations forming the polygon.
68149         var polygons = entities.multipolygon.reduce(function(polygons, m) {
68150             return polygons.concat(osmJoinWays(m.members, graph));
68151         }, []).concat(entities.closedWay.map(function(d) {
68152             var member = [{id: d.id}];
68153             member.nodes = graph.childNodes(d);
68154             return member;
68155         }));
68156
68157         // contained is an array of arrays of boolean values,
68158         // where contained[j][k] is true iff the jth way is
68159         // contained by the kth way.
68160         var contained = polygons.map(function(w, i) {
68161             return polygons.map(function(d, n) {
68162                 if (i === n) return null;
68163                 return geoPolygonContainsPolygon(
68164                     lodash.map(d.nodes, 'loc'),
68165                     lodash.map(w.nodes, 'loc'));
68166             });
68167         });
68168
68169         // Sort all polygons as either outer or inner ways
68170         var members = [],
68171             outer = true;
68172
68173         while (polygons.length) {
68174             extractUncontained(polygons);
68175             polygons = polygons.filter(isContained);
68176             contained = contained.filter(isContained).map(filterContained);
68177         }
68178
68179         function isContained(d, i) {
68180             return lodash.some(contained[i]);
68181         }
68182
68183         function filterContained(d) {
68184             return d.filter(isContained);
68185         }
68186
68187         function extractUncontained(polygons) {
68188             polygons.forEach(function(d, i) {
68189                 if (!isContained(d, i)) {
68190                     d.forEach(function(member) {
68191                         members.push({
68192                             type: 'way',
68193                             id: member.id,
68194                             role: outer ? 'outer' : 'inner'
68195                         });
68196                     });
68197                 }
68198             });
68199             outer = !outer;
68200         }
68201
68202         // Move all tags to one relation
68203         var relation = entities.multipolygon[0] ||
68204             osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
68205
68206         entities.multipolygon.slice(1).forEach(function(m) {
68207             relation = relation.mergeTags(m.tags);
68208             graph = graph.remove(m);
68209         });
68210
68211         entities.closedWay.forEach(function(way) {
68212             function isThisOuter(m) {
68213                 return m.id === way.id && m.role !== 'inner';
68214             }
68215             if (members.some(isThisOuter)) {
68216                 relation = relation.mergeTags(way.tags);
68217                 graph = graph.replace(way.update({ tags: {} }));
68218             }
68219         });
68220
68221         return graph.replace(relation.update({
68222             members: members,
68223             tags: lodash.omit(relation.tags, 'area')
68224         }));
68225     };
68226
68227
68228     action.disabled = function(graph) {
68229         var entities = groupEntities(graph);
68230         if (entities.other.length > 0 ||
68231             entities.closedWay.length + entities.multipolygon.length < 2)
68232             return 'not_eligible';
68233         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
68234             return 'incomplete_relation';
68235     };
68236
68237
68238     return action;
68239 }
68240
68241 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
68242 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
68243 //
68244 // Permission is hereby granted, free of charge, to any person
68245 // obtaining a copy of this software and associated documentation files
68246 // (the "Software"), to deal in the Software without restriction,
68247 // including without limitation the rights to use, copy, modify, merge,
68248 // publish, distribute, sublicense, and/or sell copies of the Software,
68249 // and to permit persons to whom the Software is furnished to do so,
68250 // subject to the following conditions:
68251 //
68252 // The above copyright notice and this permission notice shall be
68253 // included in all copies or substantial portions of the Software.
68254 //
68255 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
68256 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68257 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
68258 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
68259 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
68260 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
68261 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
68262 // SOFTWARE.
68263
68264 // source:  https://bitbucket.org/lshift/synchrotron/src
68265 function longest_common_subsequence(file1, file2) {
68266     /* Text diff algorithm following Hunt and McIlroy 1976.
68267      * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
68268      * comparison, Bell Telephone Laboratories CSTR #41 (1976)
68269      * http://www.cs.dartmouth.edu/~doug/
68270      *
68271      * Expects two arrays of strings.
68272      */
68273     var equivalenceClasses;
68274     var file2indices;
68275     var newCandidate;
68276     var candidates;
68277     var line;
68278     var c, i, j, jX, r, s;
68279
68280     equivalenceClasses = {};
68281     for (j = 0; j < file2.length; j++) {
68282         line = file2[j];
68283         if (equivalenceClasses[line]) {
68284             equivalenceClasses[line].push(j);
68285         } else {
68286             equivalenceClasses[line] = [j];
68287         }
68288     }
68289
68290     candidates = [{file1index: -1,
68291                    file2index: -1,
68292                    chain: null}];
68293
68294     for (i = 0; i < file1.length; i++) {
68295         line = file1[i];
68296         file2indices = equivalenceClasses[line] || [];
68297
68298         r = 0;
68299         c = candidates[0];
68300
68301         for (jX = 0; jX < file2indices.length; jX++) {
68302             j = file2indices[jX];
68303
68304             for (s = 0; s < candidates.length; s++) {
68305                 if ((candidates[s].file2index < j) &&
68306                     ((s === candidates.length - 1) ||
68307                      (candidates[s + 1].file2index > j)))
68308                     break;
68309             }
68310
68311             if (s < candidates.length) {
68312                 newCandidate = {file1index: i,
68313                                 file2index: j,
68314                                 chain: candidates[s]};
68315                 if (r === candidates.length) {
68316                     candidates.push(c);
68317                 } else {
68318                     candidates[r] = c;
68319                 }
68320                 r = s + 1;
68321                 c = newCandidate;
68322                 if (r === candidates.length) {
68323                     break; // no point in examining further (j)s
68324                 }
68325             }
68326         }
68327
68328         candidates[r] = c;
68329     }
68330
68331     // At this point, we know the LCS: it's in the reverse of the
68332     // linked-list through .chain of
68333     // candidates[candidates.length - 1].
68334
68335     return candidates[candidates.length - 1];
68336 }
68337
68338
68339
68340
68341
68342
68343
68344
68345
68346
68347
68348 function diff_indices(file1, file2) {
68349     // We apply the LCS to give a simple representation of the
68350     // offsets and lengths of mismatched chunks in the input
68351     // files. This is used by diff3_merge_indices below.
68352
68353     var result = [];
68354     var tail1 = file1.length;
68355     var tail2 = file2.length;
68356
68357     for (var candidate = longest_common_subsequence(file1, file2);
68358          candidate !== null;
68359          candidate = candidate.chain)
68360     {
68361         var mismatchLength1 = tail1 - candidate.file1index - 1;
68362         var mismatchLength2 = tail2 - candidate.file2index - 1;
68363         tail1 = candidate.file1index;
68364         tail2 = candidate.file2index;
68365
68366         if (mismatchLength1 || mismatchLength2) {
68367             result.push({file1: [tail1 + 1, mismatchLength1],
68368                          file2: [tail2 + 1, mismatchLength2]});
68369         }
68370     }
68371
68372     result.reverse();
68373     return result;
68374 }
68375
68376 function diff3_merge_indices (a, o, b) {
68377     // Given three files, A, O, and B, where both A and B are
68378     // independently derived from O, returns a fairly complicated
68379     // internal representation of merge decisions it's taken. The
68380     // interested reader may wish to consult
68381     //
68382     // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
68383     // Formal Investigation of Diff3." In Arvind and Prasad,
68384     // editors, Foundations of Software Technology and Theoretical
68385     // Computer Science (FSTTCS), December 2007.
68386     //
68387     // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
68388     var i;
68389
68390     var m1 = diff_indices(o, a);
68391     var m2 = diff_indices(o, b);
68392
68393     var hunks = [];
68394     function addHunk(h, side) {
68395         hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
68396     }
68397     for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
68398     for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
68399     hunks.sort();
68400
68401     var result = [];
68402     var commonOffset = 0;
68403     function copyCommon(targetOffset) {
68404         if (targetOffset > commonOffset) {
68405             result.push([1, commonOffset, targetOffset - commonOffset]);
68406             commonOffset = targetOffset;
68407         }
68408     }
68409
68410     for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
68411         var firstHunkIndex = hunkIndex;
68412         var hunk = hunks[hunkIndex];
68413         var regionLhs = hunk[0];
68414         var regionRhs = regionLhs + hunk[2];
68415         while (hunkIndex < hunks.length - 1) {
68416             var maybeOverlapping = hunks[hunkIndex + 1];
68417             var maybeLhs = maybeOverlapping[0];
68418             if (maybeLhs > regionRhs) break;
68419             regionRhs = maybeLhs + maybeOverlapping[2];
68420             hunkIndex++;
68421         }
68422
68423         copyCommon(regionLhs);
68424         if (firstHunkIndex === hunkIndex) {
68425     // The "overlap" was only one hunk long, meaning that
68426     // there's no conflict here. Either a and o were the
68427     // same, or b and o were the same.
68428             if (hunk[4] > 0) {
68429                 result.push([hunk[1], hunk[3], hunk[4]]);
68430             }
68431         } else {
68432     // A proper conflict. Determine the extents of the
68433     // regions involved from a, o and b. Effectively merge
68434     // all the hunks on the left into one giant hunk, and
68435     // do the same for the right; then, correct for skew
68436     // in the regions of o that each side changed, and
68437     // report appropriate spans for the three sides.
68438     var regions = {
68439         0: [a.length, -1, o.length, -1],
68440         2: [b.length, -1, o.length, -1]
68441     };
68442             for (i = firstHunkIndex; i <= hunkIndex; i++) {
68443         hunk = hunks[i];
68444                 var side = hunk[1];
68445         var r = regions[side];
68446         var oLhs = hunk[0];
68447         var oRhs = oLhs + hunk[2];
68448                 var abLhs = hunk[3];
68449                 var abRhs = abLhs + hunk[4];
68450         r[0] = Math.min(abLhs, r[0]);
68451         r[1] = Math.max(abRhs, r[1]);
68452         r[2] = Math.min(oLhs, r[2]);
68453         r[3] = Math.max(oRhs, r[3]);
68454             }
68455     var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
68456     var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
68457     var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
68458     var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
68459             result.push([-1,
68460              aLhs,      aRhs      - aLhs,
68461              regionLhs, regionRhs - regionLhs,
68462              bLhs,      bRhs      - bLhs]);
68463         }
68464         commonOffset = regionRhs;
68465     }
68466
68467     copyCommon(o.length);
68468     return result;
68469 }
68470
68471 function diff3_merge (a, o, b, excludeFalseConflicts) {
68472     // Applies the output of Diff3.diff3_merge_indices to actually
68473     // construct the merged file; the returned result alternates
68474     // between "ok" and "conflict" blocks.
68475
68476     var result = [];
68477     var files = [a, o, b];
68478     var indices = diff3_merge_indices(a, o, b);
68479
68480     var okLines = [];
68481     function flushOk() {
68482         if (okLines.length) {
68483             result.push({ok: okLines});
68484         }
68485         okLines = [];
68486     }
68487     function pushOk(xs) {
68488         for (var j = 0; j < xs.length; j++) {
68489             okLines.push(xs[j]);
68490         }
68491     }
68492
68493     function isTrueConflict(rec) {
68494         if (rec[2] !== rec[6]) return true;
68495         var aoff = rec[1];
68496         var boff = rec[5];
68497         for (var j = 0; j < rec[2]; j++) {
68498             if (a[j + aoff] !== b[j + boff]) return true;
68499         }
68500         return false;
68501     }
68502
68503     for (var i = 0; i < indices.length; i++) {
68504         var x = indices[i];
68505         var side = x[0];
68506         if (side === -1) {
68507             if (excludeFalseConflicts && !isTrueConflict(x)) {
68508                 pushOk(files[0].slice(x[1], x[1] + x[2]));
68509             } else {
68510                 flushOk();
68511                 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
68512                                         aIndex: x[1],
68513                                         o: o.slice(x[3], x[3] + x[4]),
68514                                         oIndex: x[3],
68515                                         b: b.slice(x[5], x[5] + x[6]),
68516                                         bIndex: x[5]}});
68517             }
68518         } else {
68519             pushOk(files[side].slice(x[1], x[1] + x[2]));
68520         }
68521     }
68522
68523     flushOk();
68524     return result;
68525 }
68526
68527 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
68528     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
68529         conflicts = [];
68530
68531
68532     function user(d) {
68533         return lodash.isFunction(formatUser) ? formatUser(d) : d;
68534     }
68535
68536
68537     function mergeLocation(remote, target) {
68538         function pointEqual(a, b) {
68539             var epsilon = 1e-6;
68540             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
68541         }
68542
68543         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
68544             return target;
68545         }
68546         if (option === 'force_remote') {
68547             return target.update({loc: remote.loc});
68548         }
68549
68550         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
68551         return target;
68552     }
68553
68554
68555     function mergeNodes(base, remote, target) {
68556         if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
68557             return target;
68558         }
68559         if (option === 'force_remote') {
68560             return target.update({nodes: remote.nodes});
68561         }
68562
68563         var ccount = conflicts.length,
68564             o = base.nodes || [],
68565             a = target.nodes || [],
68566             b = remote.nodes || [],
68567             nodes = [],
68568             hunks = diff3_merge(a, o, b, true);
68569
68570         for (var i = 0; i < hunks.length; i++) {
68571             var hunk = hunks[i];
68572             if (hunk.ok) {
68573                 nodes.push.apply(nodes, hunk.ok);
68574             } else {
68575                 // for all conflicts, we can assume c.a !== c.b
68576                 // because `diff3_merge` called with `true` option to exclude false conflicts..
68577                 var c = hunk.conflict;
68578                 if (lodash.isEqual(c.o, c.a)) {  // only changed remotely
68579                     nodes.push.apply(nodes, c.b);
68580                 } else if (lodash.isEqual(c.o, c.b)) {  // only changed locally
68581                     nodes.push.apply(nodes, c.a);
68582                 } else {       // changed both locally and remotely
68583                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
68584                     break;
68585                 }
68586             }
68587         }
68588
68589         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
68590     }
68591
68592
68593     function mergeChildren(targetWay, children, updates, graph) {
68594         function isUsed(node, targetWay) {
68595             var parentWays = lodash.map(graph.parentWays(node), 'id');
68596             return node.hasInterestingTags() ||
68597                 lodash.without(parentWays, targetWay.id).length > 0 ||
68598                 graph.parentRelations(node).length > 0;
68599         }
68600
68601         var ccount = conflicts.length;
68602
68603         for (var i = 0; i < children.length; i++) {
68604             var id = children[i],
68605                 node = graph.hasEntity(id);
68606
68607             // remove unused childNodes..
68608             if (targetWay.nodes.indexOf(id) === -1) {
68609                 if (node && !isUsed(node, targetWay)) {
68610                     updates.removeIds.push(id);
68611                 }
68612                 continue;
68613             }
68614
68615             // restore used childNodes..
68616             var local = localGraph.hasEntity(id),
68617                 remote = remoteGraph.hasEntity(id),
68618                 target;
68619
68620             if (option === 'force_remote' && remote && remote.visible) {
68621                 updates.replacements.push(remote);
68622
68623             } else if (option === 'force_local' && local) {
68624                 target = osmEntity$$1(local);
68625                 if (remote) {
68626                     target = target.update({ version: remote.version });
68627                 }
68628                 updates.replacements.push(target);
68629
68630             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
68631                 target = osmEntity$$1(local, { version: remote.version });
68632                 if (remote.visible) {
68633                     target = mergeLocation(remote, target);
68634                 } else {
68635                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
68636                 }
68637
68638                 if (conflicts.length !== ccount) break;
68639                 updates.replacements.push(target);
68640             }
68641         }
68642
68643         return targetWay;
68644     }
68645
68646
68647     function updateChildren(updates, graph) {
68648         for (var i = 0; i < updates.replacements.length; i++) {
68649             graph = graph.replace(updates.replacements[i]);
68650         }
68651         if (updates.removeIds.length) {
68652             graph = actionDeleteMultiple(updates.removeIds)(graph);
68653         }
68654         return graph;
68655     }
68656
68657
68658     function mergeMembers(remote, target) {
68659         if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
68660             return target;
68661         }
68662         if (option === 'force_remote') {
68663             return target.update({members: remote.members});
68664         }
68665
68666         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
68667         return target;
68668     }
68669
68670
68671     function mergeTags(base, remote, target) {
68672         function ignoreKey(k) {
68673             return lodash.includes(dataDiscarded, k);
68674         }
68675
68676         if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
68677             return target;
68678         }
68679         if (option === 'force_remote') {
68680             return target.update({tags: remote.tags});
68681         }
68682
68683         var ccount = conflicts.length,
68684             o = base.tags || {},
68685             a = target.tags || {},
68686             b = remote.tags || {},
68687             keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
68688             tags = lodash.clone(a),
68689             changed = false;
68690
68691         for (var i = 0; i < keys.length; i++) {
68692             var k = keys[i];
68693
68694             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
68695                 if (o[k] !== a[k]) {      // changed locally..
68696                     conflicts.push(t('merge_remote_changes.conflict.tags',
68697                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
68698
68699                 } else {                  // unchanged locally, accept remote change..
68700                     if (b.hasOwnProperty(k)) {
68701                         tags[k] = b[k];
68702                     } else {
68703                         delete tags[k];
68704                     }
68705                     changed = true;
68706                 }
68707             }
68708         }
68709
68710         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
68711     }
68712
68713
68714     //  `graph.base()` is the common ancestor of the two graphs.
68715     //  `localGraph` contains user's edits up to saving
68716     //  `remoteGraph` contains remote edits to modified nodes
68717     //  `graph` must be a descendent of `localGraph` and may include
68718     //      some conflict resolution actions performed on it.
68719     //
68720     //                  --- ... --- `localGraph` -- ... -- `graph`
68721     //                 /
68722     //  `graph.base()` --- ... --- `remoteGraph`
68723     //
68724     var action = function(graph) {
68725         var updates = { replacements: [], removeIds: [] },
68726             base = graph.base().entities[id],
68727             local = localGraph.entity(id),
68728             remote = remoteGraph.entity(id),
68729             target = osmEntity$$1(local, { version: remote.version });
68730
68731         // delete/undelete
68732         if (!remote.visible) {
68733             if (option === 'force_remote') {
68734                 return actionDeleteMultiple([id])(graph);
68735
68736             } else if (option === 'force_local') {
68737                 if (target.type === 'way') {
68738                     target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
68739                     graph = updateChildren(updates, graph);
68740                 }
68741                 return graph.replace(target);
68742
68743             } else {
68744                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
68745                 return graph;  // do nothing
68746             }
68747         }
68748
68749         // merge
68750         if (target.type === 'node') {
68751             target = mergeLocation(remote, target);
68752
68753         } else if (target.type === 'way') {
68754             // pull in any child nodes that may not be present locally..
68755             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
68756             target = mergeNodes(base, remote, target);
68757             target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
68758
68759         } else if (target.type === 'relation') {
68760             target = mergeMembers(remote, target);
68761         }
68762
68763         target = mergeTags(base, remote, target);
68764
68765         if (!conflicts.length) {
68766             graph = updateChildren(updates, graph).replace(target);
68767         }
68768
68769         return graph;
68770     };
68771
68772
68773     action.withOption = function(opt) {
68774         option = opt;
68775         return action;
68776     };
68777
68778
68779     action.conflicts = function() {
68780         return conflicts;
68781     };
68782
68783
68784     return action;
68785 }
68786
68787 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
68788 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
68789 function actionMove(moveIds, tryDelta, projection, cache) {
68790     var delta = tryDelta;
68791
68792     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
68793     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
68794
68795     function setupCache(graph) {
68796         function canMove(nodeId) {
68797             // Allow movement of any node that is in the selectedIDs list..
68798             if (moveIds.indexOf(nodeId) !== -1) return true;
68799
68800             // Allow movement of a vertex where 2 ways meet..
68801             var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
68802             if (parents.length < 3) return true;
68803
68804             // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
68805             var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
68806             if (!parentsMoving) delete cache.moving[nodeId];
68807
68808             return parentsMoving;
68809         }
68810
68811         function cacheEntities(ids) {
68812             ids.forEach(function(id) {
68813                 if (cache.moving[id]) return;
68814                 cache.moving[id] = true;
68815
68816                 var entity = graph.hasEntity(id);
68817                 if (!entity) return;
68818
68819                 if (entity.type === 'node') {
68820                     cache.nodes.push(id);
68821                     cache.startLoc[id] = entity.loc;
68822                 } else if (entity.type === 'way') {
68823                     cache.ways.push(id);
68824                     cacheEntities(entity.nodes);
68825                 } else {
68826                     cacheEntities(entity.members.map(function(member) {
68827                         return member.id;
68828                     }));
68829                 }
68830             });
68831         }
68832
68833         function cacheIntersections(ids) {
68834             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
68835
68836             ids.forEach(function(id) {
68837                 // consider only intersections with 1 moved and 1 unmoved way.
68838                 var childNodes = graph.childNodes(graph.entity(id));
68839                 childNodes.forEach(function(node) {
68840                     var parents = graph.parentWays(node);
68841                     if (parents.length !== 2) return;
68842
68843                     var moved = graph.entity(id),
68844                         unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
68845                     if (!unmoved) return;
68846
68847                     // exclude ways that are overly connected..
68848                     if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
68849
68850                     if (moved.isArea() || unmoved.isArea()) return;
68851
68852                     cache.intersection[node.id] = {
68853                         nodeId: node.id,
68854                         movedId: moved.id,
68855                         unmovedId: unmoved.id,
68856                         movedIsEP: isEndpoint(moved, node.id),
68857                         unmovedIsEP: isEndpoint(unmoved, node.id)
68858                     };
68859                 });
68860             });
68861         }
68862
68863
68864         if (!cache) {
68865             cache = {};
68866         }
68867         if (!cache.ok) {
68868             cache.moving = {};
68869             cache.intersection = {};
68870             cache.replacedVertex = {};
68871             cache.startLoc = {};
68872             cache.nodes = [];
68873             cache.ways = [];
68874
68875             cacheEntities(moveIds);
68876             cacheIntersections(cache.ways);
68877             cache.nodes = lodash.filter(cache.nodes, canMove);
68878
68879             cache.ok = true;
68880         }
68881     }
68882
68883
68884     // Place a vertex where the moved vertex used to be, to preserve way shape..
68885     function replaceMovedVertex(nodeId, wayId, graph, delta) {
68886         var way = graph.entity(wayId),
68887             moved = graph.entity(nodeId),
68888             movedIndex = way.nodes.indexOf(nodeId),
68889             len, prevIndex, nextIndex;
68890
68891         if (way.isClosed()) {
68892             len = way.nodes.length - 1;
68893             prevIndex = (movedIndex + len - 1) % len;
68894             nextIndex = (movedIndex + len + 1) % len;
68895         } else {
68896             len = way.nodes.length;
68897             prevIndex = movedIndex - 1;
68898             nextIndex = movedIndex + 1;
68899         }
68900
68901         var prev = graph.hasEntity(way.nodes[prevIndex]),
68902             next = graph.hasEntity(way.nodes[nextIndex]);
68903
68904         // Don't add orig vertex at endpoint..
68905         if (!prev || !next) return graph;
68906
68907         var key = wayId + '_' + nodeId,
68908             orig = cache.replacedVertex[key];
68909         if (!orig) {
68910             orig = osmNode();
68911             cache.replacedVertex[key] = orig;
68912             cache.startLoc[orig.id] = cache.startLoc[nodeId];
68913         }
68914
68915         var start, end;
68916         if (delta) {
68917             start = projection(cache.startLoc[nodeId]);
68918             end = projection.invert(vecAdd(start, delta));
68919         } else {
68920             end = cache.startLoc[nodeId];
68921         }
68922         orig = orig.move(end);
68923
68924         var angle = Math.abs(geoAngle(orig, prev, projection) -
68925                 geoAngle(orig, next, projection)) * 180 / Math.PI;
68926
68927         // Don't add orig vertex if it would just make a straight line..
68928         if (angle > 175 && angle < 185) return graph;
68929
68930         // Don't add orig vertex if another point is already nearby (within 10m)
68931         if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
68932             geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
68933
68934         // moving forward or backward along way?
68935         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
68936             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
68937             d1 = geoPathLength(p1),
68938             d2 = geoPathLength(p2),
68939             insertAt = (d1 < d2) ? movedIndex : nextIndex;
68940
68941         // moving around closed loop?
68942         if (way.isClosed() && insertAt === 0) insertAt = len;
68943
68944         way = way.addNode(orig.id, insertAt);
68945         return graph.replace(orig).replace(way);
68946     }
68947
68948
68949     // Reorder nodes around intersections that have moved..
68950     function unZorroIntersection(intersection, graph) {
68951         var vertex = graph.entity(intersection.nodeId),
68952             way1 = graph.entity(intersection.movedId),
68953             way2 = graph.entity(intersection.unmovedId),
68954             isEP1 = intersection.movedIsEP,
68955             isEP2 = intersection.unmovedIsEP;
68956
68957         // don't move the vertex if it is the endpoint of both ways.
68958         if (isEP1 && isEP2) return graph;
68959
68960         var nodes1 = lodash.without(graph.childNodes(way1), vertex),
68961             nodes2 = lodash.without(graph.childNodes(way2), vertex);
68962
68963         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
68964         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
68965
68966         var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
68967             edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
68968             loc;
68969
68970         // snap vertex to nearest edge (or some point between them)..
68971         if (!isEP1 && !isEP2) {
68972             var epsilon = 1e-4, maxIter = 10;
68973             for (var i = 0; i < maxIter; i++) {
68974                 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
68975                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
68976                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
68977                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
68978             }
68979         } else if (!isEP1) {
68980             loc = edge1.loc;
68981         } else {
68982             loc = edge2.loc;
68983         }
68984
68985         graph = graph.replace(vertex.move(loc));
68986
68987         // if zorro happened, reorder nodes..
68988         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
68989             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
68990             graph = graph.replace(way1);
68991         }
68992         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
68993             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
68994             graph = graph.replace(way2);
68995         }
68996
68997         return graph;
68998     }
68999
69000
69001     function cleanupIntersections(graph) {
69002         lodash.each(cache.intersection, function(obj) {
69003             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
69004             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
69005             graph = unZorroIntersection(obj, graph);
69006         });
69007
69008         return graph;
69009     }
69010
69011
69012     // check if moving way endpoint can cross an unmoved way, if so limit delta..
69013     function limitDelta(graph) {
69014         lodash.each(cache.intersection, function(obj) {
69015             // Don't limit movement if this is vertex joins 2 endpoints..
69016             if (obj.movedIsEP && obj.unmovedIsEP) return;
69017             // Don't limit movement if this vertex is not an endpoint anyway..
69018             if (!obj.movedIsEP) return;
69019
69020             var node = graph.entity(obj.nodeId),
69021                 start = projection(node.loc),
69022                 end = vecAdd(start, delta),
69023                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
69024                 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
69025                     function(loc) { return vecAdd(projection(loc), delta); }),
69026                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
69027                 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
69028                 hits = geoPathIntersections(movedPath, unmovedPath);
69029
69030             for (var i = 0; i < hits.length; i++) {
69031                 if (lodash.isEqual(hits[i], end)) continue;
69032                 var edge = geoChooseEdge(unmovedNodes, end, projection);
69033                 delta = vecSub(projection(edge.loc), start);
69034             }
69035         });
69036     }
69037
69038
69039     var action = function(graph) {
69040         if (delta[0] === 0 && delta[1] === 0) return graph;
69041
69042         setupCache(graph);
69043
69044         if (!lodash.isEmpty(cache.intersection)) {
69045             limitDelta(graph);
69046         }
69047
69048         lodash.each(cache.nodes, function(id) {
69049             var node = graph.entity(id),
69050                 start = projection(node.loc),
69051                 end = vecAdd(start, delta);
69052             graph = graph.replace(node.move(projection.invert(end)));
69053         });
69054
69055         if (!lodash.isEmpty(cache.intersection)) {
69056             graph = cleanupIntersections(graph);
69057         }
69058
69059         return graph;
69060     };
69061
69062
69063     action.disabled = function(graph) {
69064         function incompleteRelation(id) {
69065             var entity = graph.entity(id);
69066             return entity.type === 'relation' && !entity.isComplete(graph);
69067         }
69068
69069         if (lodash.some(moveIds, incompleteRelation))
69070             return 'incomplete_relation';
69071     };
69072
69073
69074     action.delta = function() {
69075         return delta;
69076     };
69077
69078
69079     return action;
69080 }
69081
69082 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
69083 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
69084 function actionMoveNode(nodeId, loc) {
69085     return function(graph) {
69086         return graph.replace(graph.entity(nodeId).move(loc));
69087     };
69088 }
69089
69090 function actionNoop() {
69091     return function(graph) {
69092         return graph;
69093     };
69094 }
69095
69096 /*
69097  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
69098  */
69099 function actionOrthogonalize(wayId, projection) {
69100     var threshold = 12, // degrees within right or straight to alter
69101         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
69102         upperThreshold = Math.cos(threshold * Math.PI / 180);
69103
69104
69105     var action = function(graph) {
69106         var way = graph.entity(wayId),
69107             nodes = graph.childNodes(way),
69108             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
69109             corner = {i: 0, dotp: 1},
69110             epsilon = 1e-4,
69111             i, j, score, motions;
69112
69113         if (nodes.length === 4) {
69114             for (i = 0; i < 1000; i++) {
69115                 motions = points.map(calcMotion);
69116                 points[corner.i] = addPoints(points[corner.i],motions[corner.i]);
69117                 score = corner.dotp;
69118                 if (score < epsilon) {
69119                     break;
69120                 }
69121             }
69122
69123             graph = graph.replace(graph.entity(nodes[corner.i].id)
69124                 .move(projection.invert(points[corner.i])));
69125
69126         } else {
69127             var best,
69128                 originalPoints = lodash.clone(points);
69129             score = Infinity;
69130
69131             for (i = 0; i < 1000; i++) {
69132                 motions = points.map(calcMotion);
69133                 for (j = 0; j < motions.length; j++) {
69134                     points[j] = addPoints(points[j],motions[j]);
69135                 }
69136                 var newScore = squareness(points);
69137                 if (newScore < score) {
69138                     best = lodash.clone(points);
69139                     score = newScore;
69140                 }
69141                 if (score < epsilon) {
69142                     break;
69143                 }
69144             }
69145
69146             points = best;
69147
69148             for (i = 0; i < points.length; i++) {
69149                 // only move the points that actually moved
69150                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
69151                     graph = graph.replace(graph.entity(nodes[i].id)
69152                         .move(projection.invert(points[i])));
69153                 }
69154             }
69155
69156             // remove empty nodes on straight sections
69157             for (i = 0; i < points.length; i++) {
69158                 var node = nodes[i];
69159
69160                 if (graph.parentWays(node).length > 1 ||
69161                     graph.parentRelations(node).length ||
69162                     node.hasInterestingTags()) {
69163
69164                     continue;
69165                 }
69166
69167                 var dotp = normalizedDotProduct(i, points);
69168                 if (dotp < -1 + epsilon) {
69169                     graph = actionDeleteNode(nodes[i].id)(graph);
69170                 }
69171             }
69172         }
69173
69174         return graph;
69175
69176
69177         function calcMotion(b, i, array) {
69178             var a = array[(i - 1 + array.length) % array.length],
69179                 c = array[(i + 1) % array.length],
69180                 p = subtractPoints(a, b),
69181                 q = subtractPoints(c, b),
69182                 scale, dotp;
69183
69184             scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
69185             p = normalizePoint(p, 1.0);
69186             q = normalizePoint(q, 1.0);
69187
69188             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
69189
69190             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
69191             if (array.length > 3) {
69192                 if (dotp < -0.707106781186547) {
69193                     dotp += 1.0;
69194                 }
69195             } else if (dotp && Math.abs(dotp) < corner.dotp) {
69196                 corner.i = i;
69197                 corner.dotp = Math.abs(dotp);
69198             }
69199
69200             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
69201         }
69202     };
69203
69204
69205     function squareness(points) {
69206         return points.reduce(function(sum, val, i, array) {
69207             var dotp = normalizedDotProduct(i, array);
69208
69209             dotp = filterDotProduct(dotp);
69210             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
69211         }, 0);
69212     }
69213
69214
69215     function normalizedDotProduct(i, points) {
69216         var a = points[(i - 1 + points.length) % points.length],
69217             b = points[i],
69218             c = points[(i + 1) % points.length],
69219             p = subtractPoints(a, b),
69220             q = subtractPoints(c, b);
69221
69222         p = normalizePoint(p, 1.0);
69223         q = normalizePoint(q, 1.0);
69224
69225         return p[0] * q[0] + p[1] * q[1];
69226     }
69227
69228
69229     function subtractPoints(a, b) {
69230         return [a[0] - b[0], a[1] - b[1]];
69231     }
69232
69233
69234     function addPoints(a, b) {
69235         return [a[0] + b[0], a[1] + b[1]];
69236     }
69237
69238
69239     function normalizePoint(point, scale) {
69240         var vector = [0, 0];
69241         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
69242         if (length !== 0) {
69243             vector[0] = point[0] / length;
69244             vector[1] = point[1] / length;
69245         }
69246
69247         vector[0] *= scale;
69248         vector[1] *= scale;
69249
69250         return vector;
69251     }
69252
69253
69254     function filterDotProduct(dotp) {
69255         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
69256             return dotp;
69257         }
69258
69259         return 0;
69260     }
69261
69262
69263     action.disabled = function(graph) {
69264         var way = graph.entity(wayId),
69265             nodes = graph.childNodes(way),
69266             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
69267
69268         if (squareness(points)) {
69269             return false;
69270         }
69271
69272         return 'not_squarish';
69273     };
69274
69275
69276     return action;
69277 }
69278
69279 // Split a way at the given node.
69280 //
69281 // Optionally, split only the given ways, if multiple ways share
69282 // the given node.
69283 //
69284 // This is the inverse of `iD.actionJoin`.
69285 //
69286 // For testing convenience, accepts an ID to assign to the new way.
69287 // Normally, this will be undefined and the way will automatically
69288 // be assigned a new ID.
69289 //
69290 // Reference:
69291 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
69292 //
69293 function actionSplit(nodeId, newWayIds) {
69294     var wayIds;
69295
69296     // if the way is closed, we need to search for a partner node
69297     // to split the way at.
69298     //
69299     // The following looks for a node that is both far away from
69300     // the initial node in terms of way segment length and nearby
69301     // in terms of beeline-distance. This assures that areas get
69302     // split on the most "natural" points (independent of the number
69303     // of nodes).
69304     // For example: bone-shaped areas get split across their waist
69305     // line, circles across the diameter.
69306     function splitArea(nodes, idxA, graph) {
69307         var lengths = new Array(nodes.length),
69308             length,
69309             i,
69310             best = 0,
69311             idxB;
69312
69313         function wrap(index) {
69314             return utilWrap(index, nodes.length);
69315         }
69316
69317         function dist(nA, nB) {
69318             return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
69319         }
69320
69321         // calculate lengths
69322         length = 0;
69323         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
69324             length += dist(nodes[i], nodes[wrap(i-1)]);
69325             lengths[i] = length;
69326         }
69327
69328         length = 0;
69329         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
69330             length += dist(nodes[i], nodes[wrap(i+1)]);
69331             if (length < lengths[i])
69332                 lengths[i] = length;
69333         }
69334
69335         // determine best opposite node to split
69336         for (i = 0; i < nodes.length; i++) {
69337             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
69338             if (cost > best) {
69339                 idxB = i;
69340                 best = cost;
69341             }
69342         }
69343
69344         return idxB;
69345     }
69346
69347
69348     function split(graph, wayA, newWayId) {
69349         var wayB = osmWay({id: newWayId, tags: wayA.tags}),
69350             nodesA,
69351             nodesB,
69352             isArea = wayA.isArea(),
69353             isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
69354
69355         if (wayA.isClosed()) {
69356             var nodes = wayA.nodes.slice(0, -1),
69357                 idxA = lodash.indexOf(nodes, nodeId),
69358                 idxB = splitArea(nodes, idxA, graph);
69359
69360             if (idxB < idxA) {
69361                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
69362                 nodesB = nodes.slice(idxB, idxA + 1);
69363             } else {
69364                 nodesA = nodes.slice(idxA, idxB + 1);
69365                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
69366             }
69367         } else {
69368             var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
69369             nodesA = wayA.nodes.slice(0, idx + 1);
69370             nodesB = wayA.nodes.slice(idx);
69371         }
69372
69373         wayA = wayA.update({nodes: nodesA});
69374         wayB = wayB.update({nodes: nodesB});
69375
69376         graph = graph.replace(wayA);
69377         graph = graph.replace(wayB);
69378
69379         graph.parentRelations(wayA).forEach(function(relation) {
69380             if (relation.isRestriction()) {
69381                 var via = relation.memberByRole('via');
69382                 if (via && wayB.contains(via.id)) {
69383                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
69384                     graph = graph.replace(relation);
69385                 }
69386             } else {
69387                 if (relation === isOuter) {
69388                     graph = graph.replace(relation.mergeTags(wayA.tags));
69389                     graph = graph.replace(wayA.update({tags: {}}));
69390                     graph = graph.replace(wayB.update({tags: {}}));
69391                 }
69392
69393                 var member = {
69394                     id: wayB.id,
69395                     type: 'way',
69396                     role: relation.memberById(wayA.id).role
69397                 };
69398
69399                 graph = actionAddMember(relation.id, member)(graph);
69400             }
69401         });
69402
69403         if (!isOuter && isArea) {
69404             var multipolygon = osmRelation({
69405                 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
69406                 members: [
69407                     {id: wayA.id, role: 'outer', type: 'way'},
69408                     {id: wayB.id, role: 'outer', type: 'way'}
69409                 ]});
69410
69411             graph = graph.replace(multipolygon);
69412             graph = graph.replace(wayA.update({tags: {}}));
69413             graph = graph.replace(wayB.update({tags: {}}));
69414         }
69415
69416         return graph;
69417     }
69418
69419
69420     var action = function(graph) {
69421         var candidates = action.ways(graph);
69422         for (var i = 0; i < candidates.length; i++) {
69423             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
69424         }
69425         return graph;
69426     };
69427
69428
69429     action.ways = function(graph) {
69430         var node = graph.entity(nodeId),
69431             parents = graph.parentWays(node),
69432             hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
69433
69434         return parents.filter(function(parent) {
69435             if (wayIds && wayIds.indexOf(parent.id) === -1)
69436                 return false;
69437
69438             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
69439                 return false;
69440
69441             if (parent.isClosed()) {
69442                 return true;
69443             }
69444
69445             for (var i = 1; i < parent.nodes.length - 1; i++) {
69446                 if (parent.nodes[i] === nodeId) {
69447                     return true;
69448                 }
69449             }
69450
69451             return false;
69452         });
69453     };
69454
69455
69456     action.disabled = function(graph) {
69457         var candidates = action.ways(graph);
69458         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
69459             return 'not_eligible';
69460     };
69461
69462
69463     action.limitWays = function(_) {
69464         if (!arguments.length) return wayIds;
69465         wayIds = _;
69466         return action;
69467     };
69468
69469
69470     return action;
69471 }
69472
69473 // Create a restriction relation for `turn`, which must have the following structure:
69474 //
69475 //     {
69476 //         from: { node: <node ID>, way: <way ID> },
69477 //         via:  { node: <node ID> },
69478 //         to:   { node: <node ID>, way: <way ID> },
69479 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
69480 //     }
69481 //
69482 // This specifies a restriction of type `restriction` when traveling from
69483 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
69484 // (The action does not check that these entities form a valid intersection.)
69485 //
69486 // If `restriction` is not provided, it is automatically determined by
69487 // osmInferRestriction.
69488 //
69489 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
69490 // and `to.node` are used to determine which portion of the split ways become
69491 // members of the restriction.
69492 //
69493 // For testing convenience, accepts an ID to assign to the new relation.
69494 // Normally, this will be undefined and the relation will automatically
69495 // be assigned a new ID.
69496 //
69497 function actionRestrictTurn(turn, projection, restrictionId) {
69498
69499     return function(graph) {
69500         var from = graph.entity(turn.from.way),
69501             via  = graph.entity(turn.via.node),
69502             to   = graph.entity(turn.to.way);
69503
69504         function isClosingNode(way, nodeId) {
69505             return nodeId === way.first() && nodeId === way.last();
69506         }
69507
69508         function split(toOrFrom) {
69509             var newID = toOrFrom.newID || osmWay().id;
69510             graph = actionSplit(via.id, [newID])
69511                 .limitWays([toOrFrom.way])(graph);
69512
69513             var a = graph.entity(newID),
69514                 b = graph.entity(toOrFrom.way);
69515
69516             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
69517                 return [a, b];
69518             } else {
69519                 return [b, a];
69520             }
69521         }
69522
69523         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
69524             if (turn.from.node === turn.to.node) {
69525                 // U-turn
69526                 from = to = split(turn.from)[0];
69527             } else if (turn.from.way === turn.to.way) {
69528                 // Straight-on or circular
69529                 var s = split(turn.from);
69530                 from = s[0];
69531                 to   = s[1];
69532             } else {
69533                 // Other
69534                 from = split(turn.from)[0];
69535             }
69536         }
69537
69538         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
69539             to = split(turn.to)[0];
69540         }
69541
69542         return graph.replace(osmRelation({
69543             id: restrictionId,
69544             tags: {
69545                 type: 'restriction',
69546                 restriction: turn.restriction ||
69547                     osmInferRestriction(
69548                         graph,
69549                         turn.from,
69550                         turn.via,
69551                         turn.to,
69552                         projection)
69553             },
69554             members: [
69555                 {id: from.id, type: 'way',  role: 'from'},
69556                 {id: via.id,  type: 'node', role: 'via'},
69557                 {id: to.id,   type: 'way',  role: 'to'}
69558             ]
69559         }));
69560     };
69561 }
69562
69563 function actionRevert(id) {
69564     var action = function(graph) {
69565         var entity = graph.hasEntity(id),
69566             base = graph.base().entities[id];
69567
69568         if (entity && !base) {    // entity will be removed..
69569             if (entity.type === 'node') {
69570                 graph.parentWays(entity)
69571                     .forEach(function(parent) {
69572                         parent = parent.removeNode(id);
69573                         graph = graph.replace(parent);
69574
69575                         if (parent.isDegenerate()) {
69576                             graph = actionDeleteWay(parent.id)(graph);
69577                         }
69578                     });
69579             }
69580
69581             graph.parentRelations(entity)
69582                 .forEach(function(parent) {
69583                     parent = parent.removeMembersWithID(id);
69584                     graph = graph.replace(parent);
69585
69586                     if (parent.isDegenerate()) {
69587                         graph = actionDeleteRelation(parent.id)(graph);
69588                     }
69589                 });
69590         }
69591
69592         return graph.revert(id);
69593     };
69594
69595     return action;
69596 }
69597
69598 function actionRotateWay(wayId, pivot, angle, projection) {
69599     return function(graph) {
69600         return graph.update(function(graph) {
69601             var way = graph.entity(wayId);
69602
69603             lodash.uniq(way.nodes).forEach(function(id) {
69604
69605                 var node = graph.entity(id),
69606                     point = projection(node.loc),
69607                     radial = [0,0];
69608
69609                 radial[0] = point[0] - pivot[0];
69610                 radial[1] = point[1] - pivot[1];
69611
69612                 point = [
69613                     radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + pivot[0],
69614                     radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + pivot[1]
69615                 ];
69616
69617                 graph = graph.replace(node.move(projection.invert(point)));
69618
69619             });
69620
69621         });
69622     };
69623 }
69624
69625 /*
69626  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
69627  */
69628 function actionStraighten(wayId, projection) {
69629
69630     function positionAlongWay(n, s, e) {
69631         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1]))/
69632                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
69633     }
69634
69635
69636     var action = function(graph) {
69637         var way = graph.entity(wayId),
69638             nodes = graph.childNodes(way),
69639             points = nodes.map(function(n) { return projection(n.loc); }),
69640             startPoint = points[0],
69641             endPoint = points[points.length-1],
69642             toDelete = [],
69643             i;
69644
69645         for (i = 1; i < points.length-1; i++) {
69646             var node = nodes[i],
69647                 point = points[i];
69648
69649             if (graph.parentWays(node).length > 1 ||
69650                 graph.parentRelations(node).length ||
69651                 node.hasInterestingTags()) {
69652
69653                 var u = positionAlongWay(point, startPoint, endPoint),
69654                     p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
69655                     p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]);
69656
69657                 graph = graph
69658                     .replace(graph.entity(node.id)
69659                     .move(projection.invert([p0, p1])));
69660
69661             } else {
69662                 // safe to delete
69663                 if (toDelete.indexOf(node) === -1) {
69664                     toDelete.push(node);
69665                 }
69666             }
69667         }
69668
69669         for (i = 0; i < toDelete.length; i++) {
69670             graph = actionDeleteNode(toDelete[i].id)(graph);
69671         }
69672
69673         return graph;
69674     };
69675
69676
69677     action.disabled = function(graph) {
69678         // check way isn't too bendy
69679         var way = graph.entity(wayId),
69680             nodes = graph.childNodes(way),
69681             points = nodes.map(function(n) { return projection(n.loc); }),
69682             startPoint = points[0],
69683             endPoint = points[points.length-1],
69684             threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
69685             i;
69686
69687         if (threshold === 0) {
69688             return 'too_bendy';
69689         }
69690
69691         for (i = 1; i < points.length-1; i++) {
69692             var point = points[i],
69693                 u = positionAlongWay(point, startPoint, endPoint),
69694                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
69695                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
69696                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
69697
69698             // to bendy if point is off by 20% of total start/end distance in projected space
69699             if (isNaN(dist) || dist > threshold) {
69700                 return 'too_bendy';
69701             }
69702         }
69703     };
69704
69705
69706     return action;
69707 }
69708
69709 // Remove the effects of `turn.restriction` on `turn`, which must have the
69710 // following structure:
69711 //
69712 //     {
69713 //         from: { node: <node ID>, way: <way ID> },
69714 //         via:  { node: <node ID> },
69715 //         to:   { node: <node ID>, way: <way ID> },
69716 //         restriction: <relation ID>
69717 //     }
69718 //
69719 // In the simple case, `restriction` is a reference to a `no_*` restriction
69720 // on the turn itself. In this case, it is simply deleted.
69721 //
69722 // The more complex case is where `restriction` references an `only_*`
69723 // restriction on a different turn in the same intersection. In that case,
69724 // that restriction is also deleted, but at the same time restrictions on
69725 // the turns other than the first two are created.
69726 //
69727 function actionUnrestrictTurn(turn) {
69728     return function(graph) {
69729         return actionDeleteRelation(turn.restriction)(graph);
69730     };
69731 }
69732
69733
69734
69735 var index$16 = Object.freeze({
69736         d3combobox: d3combobox,
69737         d3geoTile: d3geoTile,
69738         d3keybinding: d3keybinding
69739 });
69740
69741 /* export some legacy symbols: */
69742 var Connection = services.osm;
69743 var debug = false;
69744
69745
69746
69747
69748 var iD = Object.freeze({
69749         Connection: Connection,
69750         debug: debug,
69751         d3: index$1,
69752         lib: index$16,
69753         Context: coreContext,
69754         setAreaKeys: setAreaKeys,
69755         Difference: coreDifference,
69756         Graph: coreGraph$$1,
69757         History: coreHistory,
69758         Tree: coreTree,
69759         Entity: osmEntity$$1,
69760         Node: osmNode,
69761         Relation: osmRelation,
69762         Way: osmWay,
69763         BackgroundSource: rendererBackgroundSource,
69764         Background: rendererBackground,
69765         Features: rendererFeatures,
69766         Map: rendererMap,
69767         TileLayer: rendererTileLayer,
69768         Detect: utilDetect,
69769         actionAddEntity: actionAddEntity,
69770         actionAddMember: actionAddMember,
69771         actionAddMidpoint: actionAddMidpoint,
69772         actionAddVertex: actionAddVertex,
69773         actionChangeMember: actionChangeMember,
69774         actionChangePreset: actionChangePreset,
69775         actionChangeTags: actionChangeTags,
69776         actionCircularize: actionCircularize,
69777         actionConnect: actionConnect,
69778         actionCopyEntities: actionCopyEntities,
69779         actionDeleteMember: actionDeleteMember,
69780         actionDeleteMultiple: actionDeleteMultiple,
69781         actionDeleteNode: actionDeleteNode,
69782         actionDeleteRelation: actionDeleteRelation,
69783         actionDeleteWay: actionDeleteWay,
69784         actionDeprecateTags: actionDeprecateTags,
69785         actionDiscardTags: actionDiscardTags,
69786         actionDisconnect: actionDisconnect,
69787         actionJoin: actionJoin,
69788         actionMerge: actionMerge,
69789         actionMergePolygon: actionMergePolygon,
69790         actionMergeRemoteChanges: actionMergeRemoteChanges,
69791         actionMove: actionMove,
69792         actionMoveNode: actionMoveNode,
69793         actionNoop: actionNoop,
69794         actionOrthogonalize: actionOrthogonalize,
69795         actionRestrictTurn: actionRestrictTurn,
69796         actionReverse: actionReverse,
69797         actionRevert: actionRevert,
69798         actionRotateWay: actionRotateWay,
69799         actionSplit: actionSplit,
69800         actionStraighten: actionStraighten,
69801         actionUnrestrictTurn: actionUnrestrictTurn,
69802         behaviorAddWay: behaviorAddWay,
69803         behaviorBreathe: behaviorBreathe,
69804         behaviorCopy: behaviorCopy,
69805         behaviorDrag: behaviorDrag,
69806         behaviorDrawWay: behaviorDrawWay,
69807         behaviorDraw: behaviorDraw,
69808         behaviorEdit: behaviorEdit,
69809         behaviorHash: behaviorHash,
69810         behaviorHover: behaviorHover,
69811         behaviorLasso: behaviorLasso,
69812         behaviorPaste: behaviorPaste,
69813         behaviorSelect: behaviorSelect,
69814         behaviorTail: behaviorTail,
69815         coreContext: coreContext,
69816         coreDifference: coreDifference,
69817         coreGraph: coreGraph$$1,
69818         coreHistory: coreHistory,
69819         coreTree: coreTree,
69820         data: data,
69821         dataWikipedia: dataWikipedia,
69822         dataFeatureIcons: dataFeatureIcons,
69823         dataSuggestions: dataSuggestions,
69824         dataAddressFormats: dataAddressFormats,
69825         dataDeprecated: dataDeprecated,
69826         dataDiscarded: dataDiscarded,
69827         dataLocales: dataLocales,
69828         dataPhoneFormats: dataPhoneFormats,
69829         dataImperial: dataImperial,
69830         dataDriveLeft: dataDriveLeft,
69831         dataEn: en,
69832         geoRoundCoords: geoRoundCoords,
69833         geoInterp: geoInterp,
69834         geoCross: geoCross,
69835         geoEuclideanDistance: geoEuclideanDistance,
69836         geoLatToMeters: geoLatToMeters,
69837         geoLonToMeters: geoLonToMeters,
69838         geoMetersToLat: geoMetersToLat,
69839         geoMetersToLon: geoMetersToLon,
69840         geoOffsetToMeters: geoOffsetToMeters,
69841         geoMetersToOffset: geoMetersToOffset,
69842         geoSphericalDistance: geoSphericalDistance,
69843         geoEdgeEqual: geoEdgeEqual,
69844         geoAngle: geoAngle,
69845         geoChooseEdge: geoChooseEdge,
69846         geoLineIntersection: geoLineIntersection,
69847         geoPathIntersections: geoPathIntersections,
69848         geoPointInPolygon: geoPointInPolygon,
69849         geoPolygonContainsPolygon: geoPolygonContainsPolygon,
69850         geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
69851         geoPathLength: geoPathLength,
69852         geoExtent: geoExtent$$1,
69853         geoRawMercator: geoRawMercator,
69854         modeAddArea: modeAddArea$$1,
69855         modeAddLine: modeAddLine$$1,
69856         modeAddPoint: modeAddPoint$$1,
69857         modeBrowse: modeBrowse$$1,
69858         modeDragNode: modeDragNode$$1,
69859         modeDrawArea: modeDrawArea,
69860         modeDrawLine: modeDrawLine,
69861         modeMove: modeMove$$1,
69862         modeRotateWay: modeRotateWay$$1,
69863         modeSave: modeSave$$1,
69864         modeSelect: modeSelect,
69865         operationCircularize: operationCircularize,
69866         operationContinue: operationContinue,
69867         operationDelete: operationDelete,
69868         operationDisconnect: operationDisconnect,
69869         operationMerge: operationMerge,
69870         operationMove: operationMove,
69871         operationOrthogonalize: operationOrthogonalize,
69872         operationReverse: operationReverse,
69873         operationRotate: operationRotate,
69874         operationSplit: operationSplit,
69875         operationStraighten: operationStraighten,
69876         osmEntity: osmEntity$$1,
69877         osmNode: osmNode,
69878         osmRelation: osmRelation,
69879         osmWay: osmWay,
69880         osmIntersection: osmIntersection,
69881         osmTurn: osmTurn,
69882         osmInferRestriction: osmInferRestriction,
69883         osmLanes: osmLanes,
69884         osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
69885         osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
69886         osmJoinWays: osmJoinWays,
69887         osmOneWayTags: osmOneWayTags,
69888         osmPavedTags: osmPavedTags,
69889         osmIsInterestingTag: osmIsInterestingTag,
69890         presetCategory: presetCategory,
69891         presetCollection: presetCollection,
69892         presetField: presetField,
69893         presetPreset: presetPreset,
69894         presetIndex: presetIndex,
69895         rendererBackgroundSource: rendererBackgroundSource,
69896         rendererBackground: rendererBackground,
69897         rendererFeatures: rendererFeatures,
69898         rendererMap: rendererMap,
69899         rendererTileLayer: rendererTileLayer,
69900         services: services,
69901         svgAreas: svgAreas$$1,
69902         svgDebug: svgDebug,
69903         svgDefs: svgDefs,
69904         svgGpx: svgGpx,
69905         svgIcon: svgIcon,
69906         svgLabels: svgLabels,
69907         svgLayers: svgLayers,
69908         svgLines: svgLines$$1,
69909         svgMapillaryImages: svgMapillaryImages,
69910         svgMapillarySigns: svgMapillarySigns,
69911         svgMidpoints: svgMidpoints$$1,
69912         svgOneWaySegments: svgOneWaySegments,
69913         svgOsm: svgOsm,
69914         svgPath: svgPath,
69915         svgPointTransform: svgPointTransform,
69916         svgPoints: svgPoints$$1,
69917         svgRelationMemberTags: svgRelationMemberTags,
69918         svgTagClasses: svgTagClasses,
69919         svgTurns: svgTurns,
69920         svgVertices: svgVertices$$1,
69921         uiFields: uiFields,
69922         uiFieldDefaultcheck: uiFieldCheck,
69923         uiFieldCheck: uiFieldCheck,
69924         uiFieldTypeCombo: uiFieldCombo,
69925         uiFieldMultiCombo: uiFieldCombo,
69926         uiFieldNetworkCombo: uiFieldCombo,
69927         uiFieldCombo: uiFieldCombo,
69928         uiFieldUrl: uiFieldText,
69929         uiFieldNumber: uiFieldText,
69930         uiFieldTel: uiFieldText,
69931         uiFieldEmail: uiFieldText,
69932         uiFieldText: uiFieldText,
69933         uiFieldAccess: uiFieldAccess,
69934         uiFieldAddress: uiFieldAddress,
69935         uiFieldCycleway: uiFieldCycleway,
69936         uiFieldLanes: uiFieldLanes,
69937         uiFieldLocalized: uiFieldLocalized,
69938         uiFieldMaxspeed: uiFieldMaxspeed,
69939         uiFieldRadio: uiFieldRadio,
69940         uiFieldRestrictions: uiFieldRestrictions,
69941         uiFieldTextarea: uiFieldTextarea,
69942         uiFieldWikipedia: uiFieldWikipedia,
69943         uiIntro: uiIntro,
69944         uiInit: uiInit,
69945         uiAccount: uiAccount,
69946         uiAttribution: uiAttribution,
69947         uiBackground: uiBackground,
69948         uiCmd: uiCmd,
69949         uiCommit: uiCommit,
69950         uiConfirm: uiConfirm,
69951         uiConflicts: uiConflicts,
69952         uiContributors: uiContributors,
69953         uiDisclosure: uiDisclosure,
69954         uiEntityEditor: uiEntityEditor,
69955         uiFeatureInfo: uiFeatureInfo,
69956         uiFeatureList: uiFeatureList,
69957         uiFlash: uiFlash,
69958         uiFullScreen: uiFullScreen,
69959         uiGeolocate: uiGeolocate,
69960         uiHelp: uiHelp,
69961         uiInfo: uiInfo,
69962         uiInspector: uiInspector,
69963         uiLasso: uiLasso,
69964         uiLoading: uiLoading,
69965         uiMapData: uiMapData,
69966         uiMapInMap: uiMapInMap,
69967         uiModal: uiModal,
69968         uiModes: uiModes,
69969         uiNotice: uiNotice,
69970         uiPreset: uiPreset,
69971         uiPresetIcon: uiPresetIcon,
69972         uiPresetList: uiPresetList,
69973         uiRadialMenu: uiRadialMenu,
69974         uiRawMemberEditor: uiRawMemberEditor,
69975         uiRawMembershipEditor: uiRawMembershipEditor,
69976         uiRawTagEditor: uiRawTagEditor,
69977         uiRestore: uiRestore,
69978         uiSave: uiSave,
69979         uiScale: uiScale,
69980         uiSelectionList: uiSelectionList,
69981         uiSidebar: uiSidebar,
69982         uiSourceSwitch: uiSourceSwitch,
69983         uiSpinner: uiSpinner,
69984         uiSplash: uiSplash,
69985         uiStatus: uiStatus,
69986         uiSuccess: uiSuccess,
69987         uiTagReference: uiTagReference,
69988         uiToggle: uiToggle,
69989         uiTooltipHtml: uiTooltipHtml,
69990         uiUndoRedo: uiUndoRedo,
69991         uiViewOnOSM: uiViewOnOSM,
69992         uiZoom: uiZoom,
69993         utilTagText: utilTagText,
69994         utilEntitySelector: utilEntitySelector,
69995         utilEntityOrMemberSelector: utilEntityOrMemberSelector,
69996         utilDisplayName: utilDisplayName,
69997         utilDisplayType: utilDisplayType,
69998         utilStringQs: utilStringQs,
69999         utilQsString: utilQsString,
70000         utilPrefixDOMProperty: utilPrefixDOMProperty,
70001         utilPrefixCSSProperty: utilPrefixCSSProperty,
70002         utilSetTransform: utilSetTransform,
70003         utilEditDistance: utilEditDistance,
70004         utilFastMouse: utilFastMouse,
70005         utilGetPrototypeOf: utilGetPrototypeOf,
70006         utilAsyncMap: utilAsyncMap,
70007         utilWrap: utilWrap,
70008         utilFunctor: utilFunctor,
70009         utilSessionMutex: utilSessionMutex,
70010         utilSuggestNames: utilSuggestNames,
70011         utilTriggerEvent: utilTriggerEvent,
70012         utilGetSetValue: utilGetSetValue,
70013         d3combobox: d3combobox,
70014         d3geoTile: d3geoTile,
70015         d3keybinding: d3keybinding,
70016         validationDeprecatedTag: validationDeprecatedTag,
70017         validationManyDeletions: validationManyDeletions,
70018         validationMissingTag: validationMissingTag,
70019         validationTagSuggestsArea: validationTagSuggestsArea
70020 });
70021
70022 window.iD = iD;
70023
70024 }());
70025 //# sourceMappingURL=iD.js.map