]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
9ec2d719dfe9e121d3a9e99980ff8d11b4f1bf40
[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.2';
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, castPath(path, object), 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           } else {
3905             baseUnset(array, index);
3906           }
3907         }
3908       }
3909       return array;
3910     }
3911
3912     /**
3913      * The base implementation of `_.random` without support for returning
3914      * floating-point numbers.
3915      *
3916      * @private
3917      * @param {number} lower The lower bound.
3918      * @param {number} upper The upper bound.
3919      * @returns {number} Returns the random number.
3920      */
3921     function baseRandom(lower, upper) {
3922       return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
3923     }
3924
3925     /**
3926      * The base implementation of `_.range` and `_.rangeRight` which doesn't
3927      * coerce arguments.
3928      *
3929      * @private
3930      * @param {number} start The start of the range.
3931      * @param {number} end The end of the range.
3932      * @param {number} step The value to increment or decrement by.
3933      * @param {boolean} [fromRight] Specify iterating from right to left.
3934      * @returns {Array} Returns the range of numbers.
3935      */
3936     function baseRange(start, end, step, fromRight) {
3937       var index = -1,
3938           length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
3939           result = Array(length);
3940
3941       while (length--) {
3942         result[fromRight ? length : ++index] = start;
3943         start += step;
3944       }
3945       return result;
3946     }
3947
3948     /**
3949      * The base implementation of `_.repeat` which doesn't coerce arguments.
3950      *
3951      * @private
3952      * @param {string} string The string to repeat.
3953      * @param {number} n The number of times to repeat the string.
3954      * @returns {string} Returns the repeated string.
3955      */
3956     function baseRepeat(string, n) {
3957       var result = '';
3958       if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
3959         return result;
3960       }
3961       // Leverage the exponentiation by squaring algorithm for a faster repeat.
3962       // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
3963       do {
3964         if (n % 2) {
3965           result += string;
3966         }
3967         n = nativeFloor(n / 2);
3968         if (n) {
3969           string += string;
3970         }
3971       } while (n);
3972
3973       return result;
3974     }
3975
3976     /**
3977      * The base implementation of `_.rest` which doesn't validate or coerce arguments.
3978      *
3979      * @private
3980      * @param {Function} func The function to apply a rest parameter to.
3981      * @param {number} [start=func.length-1] The start position of the rest parameter.
3982      * @returns {Function} Returns the new function.
3983      */
3984     function baseRest(func, start) {
3985       return setToString(overRest(func, start, identity), func + '');
3986     }
3987
3988     /**
3989      * The base implementation of `_.sample`.
3990      *
3991      * @private
3992      * @param {Array|Object} collection The collection to sample.
3993      * @returns {*} Returns the random element.
3994      */
3995     function baseSample(collection) {
3996       return arraySample(values(collection));
3997     }
3998
3999     /**
4000      * The base implementation of `_.sampleSize` without param guards.
4001      *
4002      * @private
4003      * @param {Array|Object} collection The collection to sample.
4004      * @param {number} n The number of elements to sample.
4005      * @returns {Array} Returns the random elements.
4006      */
4007     function baseSampleSize(collection, n) {
4008       var array = values(collection);
4009       return shuffleSelf(array, baseClamp(n, 0, array.length));
4010     }
4011
4012     /**
4013      * The base implementation of `_.set`.
4014      *
4015      * @private
4016      * @param {Object} object The object to modify.
4017      * @param {Array|string} path The path of the property to set.
4018      * @param {*} value The value to set.
4019      * @param {Function} [customizer] The function to customize path creation.
4020      * @returns {Object} Returns `object`.
4021      */
4022     function baseSet(object, path, value, customizer) {
4023       if (!isObject(object)) {
4024         return object;
4025       }
4026       path = castPath(path, object);
4027
4028       var index = -1,
4029           length = path.length,
4030           lastIndex = length - 1,
4031           nested = object;
4032
4033       while (nested != null && ++index < length) {
4034         var key = toKey(path[index]),
4035             newValue = value;
4036
4037         if (index != lastIndex) {
4038           var objValue = nested[key];
4039           newValue = customizer ? customizer(objValue, key, nested) : undefined;
4040           if (newValue === undefined) {
4041             newValue = isObject(objValue)
4042               ? objValue
4043               : (isIndex(path[index + 1]) ? [] : {});
4044           }
4045         }
4046         assignValue(nested, key, newValue);
4047         nested = nested[key];
4048       }
4049       return object;
4050     }
4051
4052     /**
4053      * The base implementation of `setData` without support for hot loop shorting.
4054      *
4055      * @private
4056      * @param {Function} func The function to associate metadata with.
4057      * @param {*} data The metadata.
4058      * @returns {Function} Returns `func`.
4059      */
4060     var baseSetData = !metaMap ? identity : function(func, data) {
4061       metaMap.set(func, data);
4062       return func;
4063     };
4064
4065     /**
4066      * The base implementation of `setToString` without support for hot loop shorting.
4067      *
4068      * @private
4069      * @param {Function} func The function to modify.
4070      * @param {Function} string The `toString` result.
4071      * @returns {Function} Returns `func`.
4072      */
4073     var baseSetToString = !defineProperty ? identity : function(func, string) {
4074       return defineProperty(func, 'toString', {
4075         'configurable': true,
4076         'enumerable': false,
4077         'value': constant(string),
4078         'writable': true
4079       });
4080     };
4081
4082     /**
4083      * The base implementation of `_.shuffle`.
4084      *
4085      * @private
4086      * @param {Array|Object} collection The collection to shuffle.
4087      * @returns {Array} Returns the new shuffled array.
4088      */
4089     function baseShuffle(collection) {
4090       return shuffleSelf(values(collection));
4091     }
4092
4093     /**
4094      * The base implementation of `_.slice` without an iteratee call guard.
4095      *
4096      * @private
4097      * @param {Array} array The array to slice.
4098      * @param {number} [start=0] The start position.
4099      * @param {number} [end=array.length] The end position.
4100      * @returns {Array} Returns the slice of `array`.
4101      */
4102     function baseSlice(array, start, end) {
4103       var index = -1,
4104           length = array.length;
4105
4106       if (start < 0) {
4107         start = -start > length ? 0 : (length + start);
4108       }
4109       end = end > length ? length : end;
4110       if (end < 0) {
4111         end += length;
4112       }
4113       length = start > end ? 0 : ((end - start) >>> 0);
4114       start >>>= 0;
4115
4116       var result = Array(length);
4117       while (++index < length) {
4118         result[index] = array[index + start];
4119       }
4120       return result;
4121     }
4122
4123     /**
4124      * The base implementation of `_.some` without support for iteratee shorthands.
4125      *
4126      * @private
4127      * @param {Array|Object} collection The collection to iterate over.
4128      * @param {Function} predicate The function invoked per iteration.
4129      * @returns {boolean} Returns `true` if any element passes the predicate check,
4130      *  else `false`.
4131      */
4132     function baseSome(collection, predicate) {
4133       var result;
4134
4135       baseEach(collection, function(value, index, collection) {
4136         result = predicate(value, index, collection);
4137         return !result;
4138       });
4139       return !!result;
4140     }
4141
4142     /**
4143      * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
4144      * performs a binary search of `array` to determine the index at which `value`
4145      * should be inserted into `array` in order to maintain its sort order.
4146      *
4147      * @private
4148      * @param {Array} array The sorted array to inspect.
4149      * @param {*} value The value to evaluate.
4150      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4151      * @returns {number} Returns the index at which `value` should be inserted
4152      *  into `array`.
4153      */
4154     function baseSortedIndex(array, value, retHighest) {
4155       var low = 0,
4156           high = array == null ? low : array.length;
4157
4158       if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
4159         while (low < high) {
4160           var mid = (low + high) >>> 1,
4161               computed = array[mid];
4162
4163           if (computed !== null && !isSymbol(computed) &&
4164               (retHighest ? (computed <= value) : (computed < value))) {
4165             low = mid + 1;
4166           } else {
4167             high = mid;
4168           }
4169         }
4170         return high;
4171       }
4172       return baseSortedIndexBy(array, value, identity, retHighest);
4173     }
4174
4175     /**
4176      * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
4177      * which invokes `iteratee` for `value` and each element of `array` to compute
4178      * their sort ranking. The iteratee is invoked with one argument; (value).
4179      *
4180      * @private
4181      * @param {Array} array The sorted array to inspect.
4182      * @param {*} value The value to evaluate.
4183      * @param {Function} iteratee The iteratee invoked per element.
4184      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4185      * @returns {number} Returns the index at which `value` should be inserted
4186      *  into `array`.
4187      */
4188     function baseSortedIndexBy(array, value, iteratee, retHighest) {
4189       value = iteratee(value);
4190
4191       var low = 0,
4192           high = array == null ? 0 : array.length,
4193           valIsNaN = value !== value,
4194           valIsNull = value === null,
4195           valIsSymbol = isSymbol(value),
4196           valIsUndefined = value === undefined;
4197
4198       while (low < high) {
4199         var mid = nativeFloor((low + high) / 2),
4200             computed = iteratee(array[mid]),
4201             othIsDefined = computed !== undefined,
4202             othIsNull = computed === null,
4203             othIsReflexive = computed === computed,
4204             othIsSymbol = isSymbol(computed);
4205
4206         if (valIsNaN) {
4207           var setLow = retHighest || othIsReflexive;
4208         } else if (valIsUndefined) {
4209           setLow = othIsReflexive && (retHighest || othIsDefined);
4210         } else if (valIsNull) {
4211           setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
4212         } else if (valIsSymbol) {
4213           setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
4214         } else if (othIsNull || othIsSymbol) {
4215           setLow = false;
4216         } else {
4217           setLow = retHighest ? (computed <= value) : (computed < value);
4218         }
4219         if (setLow) {
4220           low = mid + 1;
4221         } else {
4222           high = mid;
4223         }
4224       }
4225       return nativeMin(high, MAX_ARRAY_INDEX);
4226     }
4227
4228     /**
4229      * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
4230      * support for iteratee shorthands.
4231      *
4232      * @private
4233      * @param {Array} array The array to inspect.
4234      * @param {Function} [iteratee] The iteratee invoked per element.
4235      * @returns {Array} Returns the new duplicate free array.
4236      */
4237     function baseSortedUniq(array, iteratee) {
4238       var index = -1,
4239           length = array.length,
4240           resIndex = 0,
4241           result = [];
4242
4243       while (++index < length) {
4244         var value = array[index],
4245             computed = iteratee ? iteratee(value) : value;
4246
4247         if (!index || !eq(computed, seen)) {
4248           var seen = computed;
4249           result[resIndex++] = value === 0 ? 0 : value;
4250         }
4251       }
4252       return result;
4253     }
4254
4255     /**
4256      * The base implementation of `_.toNumber` which doesn't ensure correct
4257      * conversions of binary, hexadecimal, or octal string values.
4258      *
4259      * @private
4260      * @param {*} value The value to process.
4261      * @returns {number} Returns the number.
4262      */
4263     function baseToNumber(value) {
4264       if (typeof value == 'number') {
4265         return value;
4266       }
4267       if (isSymbol(value)) {
4268         return NAN;
4269       }
4270       return +value;
4271     }
4272
4273     /**
4274      * The base implementation of `_.toString` which doesn't convert nullish
4275      * values to empty strings.
4276      *
4277      * @private
4278      * @param {*} value The value to process.
4279      * @returns {string} Returns the string.
4280      */
4281     function baseToString(value) {
4282       // Exit early for strings to avoid a performance hit in some environments.
4283       if (typeof value == 'string') {
4284         return value;
4285       }
4286       if (isArray(value)) {
4287         // Recursively convert values (susceptible to call stack limits).
4288         return arrayMap(value, baseToString) + '';
4289       }
4290       if (isSymbol(value)) {
4291         return symbolToString ? symbolToString.call(value) : '';
4292       }
4293       var result = (value + '');
4294       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
4295     }
4296
4297     /**
4298      * The base implementation of `_.uniqBy` without support for iteratee shorthands.
4299      *
4300      * @private
4301      * @param {Array} array The array to inspect.
4302      * @param {Function} [iteratee] The iteratee invoked per element.
4303      * @param {Function} [comparator] The comparator invoked per element.
4304      * @returns {Array} Returns the new duplicate free array.
4305      */
4306     function baseUniq(array, iteratee, comparator) {
4307       var index = -1,
4308           includes = arrayIncludes,
4309           length = array.length,
4310           isCommon = true,
4311           result = [],
4312           seen = result;
4313
4314       if (comparator) {
4315         isCommon = false;
4316         includes = arrayIncludesWith;
4317       }
4318       else if (length >= LARGE_ARRAY_SIZE) {
4319         var set = iteratee ? null : createSet(array);
4320         if (set) {
4321           return setToArray(set);
4322         }
4323         isCommon = false;
4324         includes = cacheHas;
4325         seen = new SetCache;
4326       }
4327       else {
4328         seen = iteratee ? [] : result;
4329       }
4330       outer:
4331       while (++index < length) {
4332         var value = array[index],
4333             computed = iteratee ? iteratee(value) : value;
4334
4335         value = (comparator || value !== 0) ? value : 0;
4336         if (isCommon && computed === computed) {
4337           var seenIndex = seen.length;
4338           while (seenIndex--) {
4339             if (seen[seenIndex] === computed) {
4340               continue outer;
4341             }
4342           }
4343           if (iteratee) {
4344             seen.push(computed);
4345           }
4346           result.push(value);
4347         }
4348         else if (!includes(seen, computed, comparator)) {
4349           if (seen !== result) {
4350             seen.push(computed);
4351           }
4352           result.push(value);
4353         }
4354       }
4355       return result;
4356     }
4357
4358     /**
4359      * The base implementation of `_.unset`.
4360      *
4361      * @private
4362      * @param {Object} object The object to modify.
4363      * @param {Array|string} path The property path to unset.
4364      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
4365      */
4366     function baseUnset(object, path) {
4367       path = castPath(path, object);
4368       object = parent(object, path);
4369       return object == null || delete object[toKey(last(path))];
4370     }
4371
4372     /**
4373      * The base implementation of `_.update`.
4374      *
4375      * @private
4376      * @param {Object} object The object to modify.
4377      * @param {Array|string} path The path of the property to update.
4378      * @param {Function} updater The function to produce the updated value.
4379      * @param {Function} [customizer] The function to customize path creation.
4380      * @returns {Object} Returns `object`.
4381      */
4382     function baseUpdate(object, path, updater, customizer) {
4383       return baseSet(object, path, updater(baseGet(object, path)), customizer);
4384     }
4385
4386     /**
4387      * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
4388      * without support for iteratee shorthands.
4389      *
4390      * @private
4391      * @param {Array} array The array to query.
4392      * @param {Function} predicate The function invoked per iteration.
4393      * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
4394      * @param {boolean} [fromRight] Specify iterating from right to left.
4395      * @returns {Array} Returns the slice of `array`.
4396      */
4397     function baseWhile(array, predicate, isDrop, fromRight) {
4398       var length = array.length,
4399           index = fromRight ? length : -1;
4400
4401       while ((fromRight ? index-- : ++index < length) &&
4402         predicate(array[index], index, array)) {}
4403
4404       return isDrop
4405         ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
4406         : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
4407     }
4408
4409     /**
4410      * The base implementation of `wrapperValue` which returns the result of
4411      * performing a sequence of actions on the unwrapped `value`, where each
4412      * successive action is supplied the return value of the previous.
4413      *
4414      * @private
4415      * @param {*} value The unwrapped value.
4416      * @param {Array} actions Actions to perform to resolve the unwrapped value.
4417      * @returns {*} Returns the resolved value.
4418      */
4419     function baseWrapperValue(value, actions) {
4420       var result = value;
4421       if (result instanceof LazyWrapper) {
4422         result = result.value();
4423       }
4424       return arrayReduce(actions, function(result, action) {
4425         return action.func.apply(action.thisArg, arrayPush([result], action.args));
4426       }, result);
4427     }
4428
4429     /**
4430      * The base implementation of methods like `_.xor`, without support for
4431      * iteratee shorthands, that accepts an array of arrays to inspect.
4432      *
4433      * @private
4434      * @param {Array} arrays The arrays to inspect.
4435      * @param {Function} [iteratee] The iteratee invoked per element.
4436      * @param {Function} [comparator] The comparator invoked per element.
4437      * @returns {Array} Returns the new array of values.
4438      */
4439     function baseXor(arrays, iteratee, comparator) {
4440       var length = arrays.length;
4441       if (length < 2) {
4442         return length ? baseUniq(arrays[0]) : [];
4443       }
4444       var index = -1,
4445           result = Array(length);
4446
4447       while (++index < length) {
4448         var array = arrays[index],
4449             othIndex = -1;
4450
4451         while (++othIndex < length) {
4452           if (othIndex != index) {
4453             result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
4454           }
4455         }
4456       }
4457       return baseUniq(baseFlatten(result, 1), iteratee, comparator);
4458     }
4459
4460     /**
4461      * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
4462      *
4463      * @private
4464      * @param {Array} props The property identifiers.
4465      * @param {Array} values The property values.
4466      * @param {Function} assignFunc The function to assign values.
4467      * @returns {Object} Returns the new object.
4468      */
4469     function baseZipObject(props, values, assignFunc) {
4470       var index = -1,
4471           length = props.length,
4472           valsLength = values.length,
4473           result = {};
4474
4475       while (++index < length) {
4476         var value = index < valsLength ? values[index] : undefined;
4477         assignFunc(result, props[index], value);
4478       }
4479       return result;
4480     }
4481
4482     /**
4483      * Casts `value` to an empty array if it's not an array like object.
4484      *
4485      * @private
4486      * @param {*} value The value to inspect.
4487      * @returns {Array|Object} Returns the cast array-like object.
4488      */
4489     function castArrayLikeObject(value) {
4490       return isArrayLikeObject(value) ? value : [];
4491     }
4492
4493     /**
4494      * Casts `value` to `identity` if it's not a function.
4495      *
4496      * @private
4497      * @param {*} value The value to inspect.
4498      * @returns {Function} Returns cast function.
4499      */
4500     function castFunction(value) {
4501       return typeof value == 'function' ? value : identity;
4502     }
4503
4504     /**
4505      * Casts `value` to a path array if it's not one.
4506      *
4507      * @private
4508      * @param {*} value The value to inspect.
4509      * @param {Object} [object] The object to query keys on.
4510      * @returns {Array} Returns the cast property path array.
4511      */
4512     function castPath(value, object) {
4513       if (isArray(value)) {
4514         return value;
4515       }
4516       return isKey(value, object) ? [value] : stringToPath(toString(value));
4517     }
4518
4519     /**
4520      * A `baseRest` alias which can be replaced with `identity` by module
4521      * replacement plugins.
4522      *
4523      * @private
4524      * @type {Function}
4525      * @param {Function} func The function to apply a rest parameter to.
4526      * @returns {Function} Returns the new function.
4527      */
4528     var castRest = baseRest;
4529
4530     /**
4531      * Casts `array` to a slice if it's needed.
4532      *
4533      * @private
4534      * @param {Array} array The array to inspect.
4535      * @param {number} start The start position.
4536      * @param {number} [end=array.length] The end position.
4537      * @returns {Array} Returns the cast slice.
4538      */
4539     function castSlice(array, start, end) {
4540       var length = array.length;
4541       end = end === undefined ? length : end;
4542       return (!start && end >= length) ? array : baseSlice(array, start, end);
4543     }
4544
4545     /**
4546      * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
4547      *
4548      * @private
4549      * @param {number|Object} id The timer id or timeout object of the timer to clear.
4550      */
4551     var clearTimeout = ctxClearTimeout || function(id) {
4552       return root.clearTimeout(id);
4553     };
4554
4555     /**
4556      * Creates a clone of  `buffer`.
4557      *
4558      * @private
4559      * @param {Buffer} buffer The buffer to clone.
4560      * @param {boolean} [isDeep] Specify a deep clone.
4561      * @returns {Buffer} Returns the cloned buffer.
4562      */
4563     function cloneBuffer(buffer, isDeep) {
4564       if (isDeep) {
4565         return buffer.slice();
4566       }
4567       var length = buffer.length,
4568           result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
4569
4570       buffer.copy(result);
4571       return result;
4572     }
4573
4574     /**
4575      * Creates a clone of `arrayBuffer`.
4576      *
4577      * @private
4578      * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
4579      * @returns {ArrayBuffer} Returns the cloned array buffer.
4580      */
4581     function cloneArrayBuffer(arrayBuffer) {
4582       var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
4583       new Uint8Array(result).set(new Uint8Array(arrayBuffer));
4584       return result;
4585     }
4586
4587     /**
4588      * Creates a clone of `dataView`.
4589      *
4590      * @private
4591      * @param {Object} dataView The data view to clone.
4592      * @param {boolean} [isDeep] Specify a deep clone.
4593      * @returns {Object} Returns the cloned data view.
4594      */
4595     function cloneDataView(dataView, isDeep) {
4596       var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
4597       return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
4598     }
4599
4600     /**
4601      * Creates a clone of `map`.
4602      *
4603      * @private
4604      * @param {Object} map The map to clone.
4605      * @param {Function} cloneFunc The function to clone values.
4606      * @param {boolean} [isDeep] Specify a deep clone.
4607      * @returns {Object} Returns the cloned map.
4608      */
4609     function cloneMap(map, isDeep, cloneFunc) {
4610       var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
4611       return arrayReduce(array, addMapEntry, new map.constructor);
4612     }
4613
4614     /**
4615      * Creates a clone of `regexp`.
4616      *
4617      * @private
4618      * @param {Object} regexp The regexp to clone.
4619      * @returns {Object} Returns the cloned regexp.
4620      */
4621     function cloneRegExp(regexp) {
4622       var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
4623       result.lastIndex = regexp.lastIndex;
4624       return result;
4625     }
4626
4627     /**
4628      * Creates a clone of `set`.
4629      *
4630      * @private
4631      * @param {Object} set The set to clone.
4632      * @param {Function} cloneFunc The function to clone values.
4633      * @param {boolean} [isDeep] Specify a deep clone.
4634      * @returns {Object} Returns the cloned set.
4635      */
4636     function cloneSet(set, isDeep, cloneFunc) {
4637       var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
4638       return arrayReduce(array, addSetEntry, new set.constructor);
4639     }
4640
4641     /**
4642      * Creates a clone of the `symbol` object.
4643      *
4644      * @private
4645      * @param {Object} symbol The symbol object to clone.
4646      * @returns {Object} Returns the cloned symbol object.
4647      */
4648     function cloneSymbol(symbol) {
4649       return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
4650     }
4651
4652     /**
4653      * Creates a clone of `typedArray`.
4654      *
4655      * @private
4656      * @param {Object} typedArray The typed array to clone.
4657      * @param {boolean} [isDeep] Specify a deep clone.
4658      * @returns {Object} Returns the cloned typed array.
4659      */
4660     function cloneTypedArray(typedArray, isDeep) {
4661       var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
4662       return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
4663     }
4664
4665     /**
4666      * Compares values to sort them in ascending order.
4667      *
4668      * @private
4669      * @param {*} value The value to compare.
4670      * @param {*} other The other value to compare.
4671      * @returns {number} Returns the sort order indicator for `value`.
4672      */
4673     function compareAscending(value, other) {
4674       if (value !== other) {
4675         var valIsDefined = value !== undefined,
4676             valIsNull = value === null,
4677             valIsReflexive = value === value,
4678             valIsSymbol = isSymbol(value);
4679
4680         var othIsDefined = other !== undefined,
4681             othIsNull = other === null,
4682             othIsReflexive = other === other,
4683             othIsSymbol = isSymbol(other);
4684
4685         if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
4686             (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
4687             (valIsNull && othIsDefined && othIsReflexive) ||
4688             (!valIsDefined && othIsReflexive) ||
4689             !valIsReflexive) {
4690           return 1;
4691         }
4692         if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
4693             (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
4694             (othIsNull && valIsDefined && valIsReflexive) ||
4695             (!othIsDefined && valIsReflexive) ||
4696             !othIsReflexive) {
4697           return -1;
4698         }
4699       }
4700       return 0;
4701     }
4702
4703     /**
4704      * Used by `_.orderBy` to compare multiple properties of a value to another
4705      * and stable sort them.
4706      *
4707      * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
4708      * specify an order of "desc" for descending or "asc" for ascending sort order
4709      * of corresponding values.
4710      *
4711      * @private
4712      * @param {Object} object The object to compare.
4713      * @param {Object} other The other object to compare.
4714      * @param {boolean[]|string[]} orders The order to sort by for each property.
4715      * @returns {number} Returns the sort order indicator for `object`.
4716      */
4717     function compareMultiple(object, other, orders) {
4718       var index = -1,
4719           objCriteria = object.criteria,
4720           othCriteria = other.criteria,
4721           length = objCriteria.length,
4722           ordersLength = orders.length;
4723
4724       while (++index < length) {
4725         var result = compareAscending(objCriteria[index], othCriteria[index]);
4726         if (result) {
4727           if (index >= ordersLength) {
4728             return result;
4729           }
4730           var order = orders[index];
4731           return result * (order == 'desc' ? -1 : 1);
4732         }
4733       }
4734       // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
4735       // that causes it, under certain circumstances, to provide the same value for
4736       // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
4737       // for more details.
4738       //
4739       // This also ensures a stable sort in V8 and other engines.
4740       // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
4741       return object.index - other.index;
4742     }
4743
4744     /**
4745      * Creates an array that is the composition of partially applied arguments,
4746      * placeholders, and provided arguments into a single array of arguments.
4747      *
4748      * @private
4749      * @param {Array} args The provided arguments.
4750      * @param {Array} partials The arguments to prepend to those provided.
4751      * @param {Array} holders The `partials` placeholder indexes.
4752      * @params {boolean} [isCurried] Specify composing for a curried function.
4753      * @returns {Array} Returns the new array of composed arguments.
4754      */
4755     function composeArgs(args, partials, holders, isCurried) {
4756       var argsIndex = -1,
4757           argsLength = args.length,
4758           holdersLength = holders.length,
4759           leftIndex = -1,
4760           leftLength = partials.length,
4761           rangeLength = nativeMax(argsLength - holdersLength, 0),
4762           result = Array(leftLength + rangeLength),
4763           isUncurried = !isCurried;
4764
4765       while (++leftIndex < leftLength) {
4766         result[leftIndex] = partials[leftIndex];
4767       }
4768       while (++argsIndex < holdersLength) {
4769         if (isUncurried || argsIndex < argsLength) {
4770           result[holders[argsIndex]] = args[argsIndex];
4771         }
4772       }
4773       while (rangeLength--) {
4774         result[leftIndex++] = args[argsIndex++];
4775       }
4776       return result;
4777     }
4778
4779     /**
4780      * This function is like `composeArgs` except that the arguments composition
4781      * is tailored for `_.partialRight`.
4782      *
4783      * @private
4784      * @param {Array} args The provided arguments.
4785      * @param {Array} partials The arguments to append to those provided.
4786      * @param {Array} holders The `partials` placeholder indexes.
4787      * @params {boolean} [isCurried] Specify composing for a curried function.
4788      * @returns {Array} Returns the new array of composed arguments.
4789      */
4790     function composeArgsRight(args, partials, holders, isCurried) {
4791       var argsIndex = -1,
4792           argsLength = args.length,
4793           holdersIndex = -1,
4794           holdersLength = holders.length,
4795           rightIndex = -1,
4796           rightLength = partials.length,
4797           rangeLength = nativeMax(argsLength - holdersLength, 0),
4798           result = Array(rangeLength + rightLength),
4799           isUncurried = !isCurried;
4800
4801       while (++argsIndex < rangeLength) {
4802         result[argsIndex] = args[argsIndex];
4803       }
4804       var offset = argsIndex;
4805       while (++rightIndex < rightLength) {
4806         result[offset + rightIndex] = partials[rightIndex];
4807       }
4808       while (++holdersIndex < holdersLength) {
4809         if (isUncurried || argsIndex < argsLength) {
4810           result[offset + holders[holdersIndex]] = args[argsIndex++];
4811         }
4812       }
4813       return result;
4814     }
4815
4816     /**
4817      * Copies the values of `source` to `array`.
4818      *
4819      * @private
4820      * @param {Array} source The array to copy values from.
4821      * @param {Array} [array=[]] The array to copy values to.
4822      * @returns {Array} Returns `array`.
4823      */
4824     function copyArray(source, array) {
4825       var index = -1,
4826           length = source.length;
4827
4828       array || (array = Array(length));
4829       while (++index < length) {
4830         array[index] = source[index];
4831       }
4832       return array;
4833     }
4834
4835     /**
4836      * Copies properties of `source` to `object`.
4837      *
4838      * @private
4839      * @param {Object} source The object to copy properties from.
4840      * @param {Array} props The property identifiers to copy.
4841      * @param {Object} [object={}] The object to copy properties to.
4842      * @param {Function} [customizer] The function to customize copied values.
4843      * @returns {Object} Returns `object`.
4844      */
4845     function copyObject(source, props, object, customizer) {
4846       var isNew = !object;
4847       object || (object = {});
4848
4849       var index = -1,
4850           length = props.length;
4851
4852       while (++index < length) {
4853         var key = props[index];
4854
4855         var newValue = customizer
4856           ? customizer(object[key], source[key], key, object, source)
4857           : undefined;
4858
4859         if (newValue === undefined) {
4860           newValue = source[key];
4861         }
4862         if (isNew) {
4863           baseAssignValue(object, key, newValue);
4864         } else {
4865           assignValue(object, key, newValue);
4866         }
4867       }
4868       return object;
4869     }
4870
4871     /**
4872      * Copies own symbols of `source` to `object`.
4873      *
4874      * @private
4875      * @param {Object} source The object to copy symbols from.
4876      * @param {Object} [object={}] The object to copy symbols to.
4877      * @returns {Object} Returns `object`.
4878      */
4879     function copySymbols(source, object) {
4880       return copyObject(source, getSymbols(source), object);
4881     }
4882
4883     /**
4884      * Copies own and inherited symbols of `source` to `object`.
4885      *
4886      * @private
4887      * @param {Object} source The object to copy symbols from.
4888      * @param {Object} [object={}] The object to copy symbols to.
4889      * @returns {Object} Returns `object`.
4890      */
4891     function copySymbolsIn(source, object) {
4892       return copyObject(source, getSymbolsIn(source), object);
4893     }
4894
4895     /**
4896      * Creates a function like `_.groupBy`.
4897      *
4898      * @private
4899      * @param {Function} setter The function to set accumulator values.
4900      * @param {Function} [initializer] The accumulator object initializer.
4901      * @returns {Function} Returns the new aggregator function.
4902      */
4903     function createAggregator(setter, initializer) {
4904       return function(collection, iteratee) {
4905         var func = isArray(collection) ? arrayAggregator : baseAggregator,
4906             accumulator = initializer ? initializer() : {};
4907
4908         return func(collection, setter, getIteratee(iteratee, 2), accumulator);
4909       };
4910     }
4911
4912     /**
4913      * Creates a function like `_.assign`.
4914      *
4915      * @private
4916      * @param {Function} assigner The function to assign values.
4917      * @returns {Function} Returns the new assigner function.
4918      */
4919     function createAssigner(assigner) {
4920       return baseRest(function(object, sources) {
4921         var index = -1,
4922             length = sources.length,
4923             customizer = length > 1 ? sources[length - 1] : undefined,
4924             guard = length > 2 ? sources[2] : undefined;
4925
4926         customizer = (assigner.length > 3 && typeof customizer == 'function')
4927           ? (length--, customizer)
4928           : undefined;
4929
4930         if (guard && isIterateeCall(sources[0], sources[1], guard)) {
4931           customizer = length < 3 ? undefined : customizer;
4932           length = 1;
4933         }
4934         object = Object(object);
4935         while (++index < length) {
4936           var source = sources[index];
4937           if (source) {
4938             assigner(object, source, index, customizer);
4939           }
4940         }
4941         return object;
4942       });
4943     }
4944
4945     /**
4946      * Creates a `baseEach` or `baseEachRight` function.
4947      *
4948      * @private
4949      * @param {Function} eachFunc The function to iterate over a collection.
4950      * @param {boolean} [fromRight] Specify iterating from right to left.
4951      * @returns {Function} Returns the new base function.
4952      */
4953     function createBaseEach(eachFunc, fromRight) {
4954       return function(collection, iteratee) {
4955         if (collection == null) {
4956           return collection;
4957         }
4958         if (!isArrayLike(collection)) {
4959           return eachFunc(collection, iteratee);
4960         }
4961         var length = collection.length,
4962             index = fromRight ? length : -1,
4963             iterable = Object(collection);
4964
4965         while ((fromRight ? index-- : ++index < length)) {
4966           if (iteratee(iterable[index], index, iterable) === false) {
4967             break;
4968           }
4969         }
4970         return collection;
4971       };
4972     }
4973
4974     /**
4975      * Creates a base function for methods like `_.forIn` and `_.forOwn`.
4976      *
4977      * @private
4978      * @param {boolean} [fromRight] Specify iterating from right to left.
4979      * @returns {Function} Returns the new base function.
4980      */
4981     function createBaseFor(fromRight) {
4982       return function(object, iteratee, keysFunc) {
4983         var index = -1,
4984             iterable = Object(object),
4985             props = keysFunc(object),
4986             length = props.length;
4987
4988         while (length--) {
4989           var key = props[fromRight ? length : ++index];
4990           if (iteratee(iterable[key], key, iterable) === false) {
4991             break;
4992           }
4993         }
4994         return object;
4995       };
4996     }
4997
4998     /**
4999      * Creates a function that wraps `func` to invoke it with the optional `this`
5000      * binding of `thisArg`.
5001      *
5002      * @private
5003      * @param {Function} func The function to wrap.
5004      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5005      * @param {*} [thisArg] The `this` binding of `func`.
5006      * @returns {Function} Returns the new wrapped function.
5007      */
5008     function createBind(func, bitmask, thisArg) {
5009       var isBind = bitmask & WRAP_BIND_FLAG,
5010           Ctor = createCtor(func);
5011
5012       function wrapper() {
5013         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5014         return fn.apply(isBind ? thisArg : this, arguments);
5015       }
5016       return wrapper;
5017     }
5018
5019     /**
5020      * Creates a function like `_.lowerFirst`.
5021      *
5022      * @private
5023      * @param {string} methodName The name of the `String` case method to use.
5024      * @returns {Function} Returns the new case function.
5025      */
5026     function createCaseFirst(methodName) {
5027       return function(string) {
5028         string = toString(string);
5029
5030         var strSymbols = hasUnicode(string)
5031           ? stringToArray(string)
5032           : undefined;
5033
5034         var chr = strSymbols
5035           ? strSymbols[0]
5036           : string.charAt(0);
5037
5038         var trailing = strSymbols
5039           ? castSlice(strSymbols, 1).join('')
5040           : string.slice(1);
5041
5042         return chr[methodName]() + trailing;
5043       };
5044     }
5045
5046     /**
5047      * Creates a function like `_.camelCase`.
5048      *
5049      * @private
5050      * @param {Function} callback The function to combine each word.
5051      * @returns {Function} Returns the new compounder function.
5052      */
5053     function createCompounder(callback) {
5054       return function(string) {
5055         return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
5056       };
5057     }
5058
5059     /**
5060      * Creates a function that produces an instance of `Ctor` regardless of
5061      * whether it was invoked as part of a `new` expression or by `call` or `apply`.
5062      *
5063      * @private
5064      * @param {Function} Ctor The constructor to wrap.
5065      * @returns {Function} Returns the new wrapped function.
5066      */
5067     function createCtor(Ctor) {
5068       return function() {
5069         // Use a `switch` statement to work with class constructors. See
5070         // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
5071         // for more details.
5072         var args = arguments;
5073         switch (args.length) {
5074           case 0: return new Ctor;
5075           case 1: return new Ctor(args[0]);
5076           case 2: return new Ctor(args[0], args[1]);
5077           case 3: return new Ctor(args[0], args[1], args[2]);
5078           case 4: return new Ctor(args[0], args[1], args[2], args[3]);
5079           case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
5080           case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
5081           case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
5082         }
5083         var thisBinding = baseCreate(Ctor.prototype),
5084             result = Ctor.apply(thisBinding, args);
5085
5086         // Mimic the constructor's `return` behavior.
5087         // See https://es5.github.io/#x13.2.2 for more details.
5088         return isObject(result) ? result : thisBinding;
5089       };
5090     }
5091
5092     /**
5093      * Creates a function that wraps `func` to enable currying.
5094      *
5095      * @private
5096      * @param {Function} func The function to wrap.
5097      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5098      * @param {number} arity The arity of `func`.
5099      * @returns {Function} Returns the new wrapped function.
5100      */
5101     function createCurry(func, bitmask, arity) {
5102       var Ctor = createCtor(func);
5103
5104       function wrapper() {
5105         var length = arguments.length,
5106             args = Array(length),
5107             index = length,
5108             placeholder = getHolder(wrapper);
5109
5110         while (index--) {
5111           args[index] = arguments[index];
5112         }
5113         var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
5114           ? []
5115           : replaceHolders(args, placeholder);
5116
5117         length -= holders.length;
5118         if (length < arity) {
5119           return createRecurry(
5120             func, bitmask, createHybrid, wrapper.placeholder, undefined,
5121             args, holders, undefined, undefined, arity - length);
5122         }
5123         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5124         return apply(fn, this, args);
5125       }
5126       return wrapper;
5127     }
5128
5129     /**
5130      * Creates a `_.find` or `_.findLast` function.
5131      *
5132      * @private
5133      * @param {Function} findIndexFunc The function to find the collection index.
5134      * @returns {Function} Returns the new find function.
5135      */
5136     function createFind(findIndexFunc) {
5137       return function(collection, predicate, fromIndex) {
5138         var iterable = Object(collection);
5139         if (!isArrayLike(collection)) {
5140           var iteratee = getIteratee(predicate, 3);
5141           collection = keys(collection);
5142           predicate = function(key) { return iteratee(iterable[key], key, iterable); };
5143         }
5144         var index = findIndexFunc(collection, predicate, fromIndex);
5145         return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
5146       };
5147     }
5148
5149     /**
5150      * Creates a `_.flow` or `_.flowRight` function.
5151      *
5152      * @private
5153      * @param {boolean} [fromRight] Specify iterating from right to left.
5154      * @returns {Function} Returns the new flow function.
5155      */
5156     function createFlow(fromRight) {
5157       return flatRest(function(funcs) {
5158         var length = funcs.length,
5159             index = length,
5160             prereq = LodashWrapper.prototype.thru;
5161
5162         if (fromRight) {
5163           funcs.reverse();
5164         }
5165         while (index--) {
5166           var func = funcs[index];
5167           if (typeof func != 'function') {
5168             throw new TypeError(FUNC_ERROR_TEXT);
5169           }
5170           if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
5171             var wrapper = new LodashWrapper([], true);
5172           }
5173         }
5174         index = wrapper ? index : length;
5175         while (++index < length) {
5176           func = funcs[index];
5177
5178           var funcName = getFuncName(func),
5179               data = funcName == 'wrapper' ? getData(func) : undefined;
5180
5181           if (data && isLaziable(data[0]) &&
5182                 data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
5183                 !data[4].length && data[9] == 1
5184               ) {
5185             wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
5186           } else {
5187             wrapper = (func.length == 1 && isLaziable(func))
5188               ? wrapper[funcName]()
5189               : wrapper.thru(func);
5190           }
5191         }
5192         return function() {
5193           var args = arguments,
5194               value = args[0];
5195
5196           if (wrapper && args.length == 1 &&
5197               isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
5198             return wrapper.plant(value).value();
5199           }
5200           var index = 0,
5201               result = length ? funcs[index].apply(this, args) : value;
5202
5203           while (++index < length) {
5204             result = funcs[index].call(this, result);
5205           }
5206           return result;
5207         };
5208       });
5209     }
5210
5211     /**
5212      * Creates a function that wraps `func` to invoke it with optional `this`
5213      * binding of `thisArg`, partial application, and currying.
5214      *
5215      * @private
5216      * @param {Function|string} func The function or method name to wrap.
5217      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5218      * @param {*} [thisArg] The `this` binding of `func`.
5219      * @param {Array} [partials] The arguments to prepend to those provided to
5220      *  the new function.
5221      * @param {Array} [holders] The `partials` placeholder indexes.
5222      * @param {Array} [partialsRight] The arguments to append to those provided
5223      *  to the new function.
5224      * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
5225      * @param {Array} [argPos] The argument positions of the new function.
5226      * @param {number} [ary] The arity cap of `func`.
5227      * @param {number} [arity] The arity of `func`.
5228      * @returns {Function} Returns the new wrapped function.
5229      */
5230     function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
5231       var isAry = bitmask & WRAP_ARY_FLAG,
5232           isBind = bitmask & WRAP_BIND_FLAG,
5233           isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
5234           isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
5235           isFlip = bitmask & WRAP_FLIP_FLAG,
5236           Ctor = isBindKey ? undefined : createCtor(func);
5237
5238       function wrapper() {
5239         var length = arguments.length,
5240             args = Array(length),
5241             index = length;
5242
5243         while (index--) {
5244           args[index] = arguments[index];
5245         }
5246         if (isCurried) {
5247           var placeholder = getHolder(wrapper),
5248               holdersCount = countHolders(args, placeholder);
5249         }
5250         if (partials) {
5251           args = composeArgs(args, partials, holders, isCurried);
5252         }
5253         if (partialsRight) {
5254           args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
5255         }
5256         length -= holdersCount;
5257         if (isCurried && length < arity) {
5258           var newHolders = replaceHolders(args, placeholder);
5259           return createRecurry(
5260             func, bitmask, createHybrid, wrapper.placeholder, thisArg,
5261             args, newHolders, argPos, ary, arity - length
5262           );
5263         }
5264         var thisBinding = isBind ? thisArg : this,
5265             fn = isBindKey ? thisBinding[func] : func;
5266
5267         length = args.length;
5268         if (argPos) {
5269           args = reorder(args, argPos);
5270         } else if (isFlip && length > 1) {
5271           args.reverse();
5272         }
5273         if (isAry && ary < length) {
5274           args.length = ary;
5275         }
5276         if (this && this !== root && this instanceof wrapper) {
5277           fn = Ctor || createCtor(fn);
5278         }
5279         return fn.apply(thisBinding, args);
5280       }
5281       return wrapper;
5282     }
5283
5284     /**
5285      * Creates a function like `_.invertBy`.
5286      *
5287      * @private
5288      * @param {Function} setter The function to set accumulator values.
5289      * @param {Function} toIteratee The function to resolve iteratees.
5290      * @returns {Function} Returns the new inverter function.
5291      */
5292     function createInverter(setter, toIteratee) {
5293       return function(object, iteratee) {
5294         return baseInverter(object, setter, toIteratee(iteratee), {});
5295       };
5296     }
5297
5298     /**
5299      * Creates a function that performs a mathematical operation on two values.
5300      *
5301      * @private
5302      * @param {Function} operator The function to perform the operation.
5303      * @param {number} [defaultValue] The value used for `undefined` arguments.
5304      * @returns {Function} Returns the new mathematical operation function.
5305      */
5306     function createMathOperation(operator, defaultValue) {
5307       return function(value, other) {
5308         var result;
5309         if (value === undefined && other === undefined) {
5310           return defaultValue;
5311         }
5312         if (value !== undefined) {
5313           result = value;
5314         }
5315         if (other !== undefined) {
5316           if (result === undefined) {
5317             return other;
5318           }
5319           if (typeof value == 'string' || typeof other == 'string') {
5320             value = baseToString(value);
5321             other = baseToString(other);
5322           } else {
5323             value = baseToNumber(value);
5324             other = baseToNumber(other);
5325           }
5326           result = operator(value, other);
5327         }
5328         return result;
5329       };
5330     }
5331
5332     /**
5333      * Creates a function like `_.over`.
5334      *
5335      * @private
5336      * @param {Function} arrayFunc The function to iterate over iteratees.
5337      * @returns {Function} Returns the new over function.
5338      */
5339     function createOver(arrayFunc) {
5340       return flatRest(function(iteratees) {
5341         iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
5342         return baseRest(function(args) {
5343           var thisArg = this;
5344           return arrayFunc(iteratees, function(iteratee) {
5345             return apply(iteratee, thisArg, args);
5346           });
5347         });
5348       });
5349     }
5350
5351     /**
5352      * Creates the padding for `string` based on `length`. The `chars` string
5353      * is truncated if the number of characters exceeds `length`.
5354      *
5355      * @private
5356      * @param {number} length The padding length.
5357      * @param {string} [chars=' '] The string used as padding.
5358      * @returns {string} Returns the padding for `string`.
5359      */
5360     function createPadding(length, chars) {
5361       chars = chars === undefined ? ' ' : baseToString(chars);
5362
5363       var charsLength = chars.length;
5364       if (charsLength < 2) {
5365         return charsLength ? baseRepeat(chars, length) : chars;
5366       }
5367       var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
5368       return hasUnicode(chars)
5369         ? castSlice(stringToArray(result), 0, length).join('')
5370         : result.slice(0, length);
5371     }
5372
5373     /**
5374      * Creates a function that wraps `func` to invoke it with the `this` binding
5375      * of `thisArg` and `partials` prepended to the arguments it receives.
5376      *
5377      * @private
5378      * @param {Function} func The function to wrap.
5379      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5380      * @param {*} thisArg The `this` binding of `func`.
5381      * @param {Array} partials The arguments to prepend to those provided to
5382      *  the new function.
5383      * @returns {Function} Returns the new wrapped function.
5384      */
5385     function createPartial(func, bitmask, thisArg, partials) {
5386       var isBind = bitmask & WRAP_BIND_FLAG,
5387           Ctor = createCtor(func);
5388
5389       function wrapper() {
5390         var argsIndex = -1,
5391             argsLength = arguments.length,
5392             leftIndex = -1,
5393             leftLength = partials.length,
5394             args = Array(leftLength + argsLength),
5395             fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5396
5397         while (++leftIndex < leftLength) {
5398           args[leftIndex] = partials[leftIndex];
5399         }
5400         while (argsLength--) {
5401           args[leftIndex++] = arguments[++argsIndex];
5402         }
5403         return apply(fn, isBind ? thisArg : this, args);
5404       }
5405       return wrapper;
5406     }
5407
5408     /**
5409      * Creates a `_.range` or `_.rangeRight` function.
5410      *
5411      * @private
5412      * @param {boolean} [fromRight] Specify iterating from right to left.
5413      * @returns {Function} Returns the new range function.
5414      */
5415     function createRange(fromRight) {
5416       return function(start, end, step) {
5417         if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
5418           end = step = undefined;
5419         }
5420         // Ensure the sign of `-0` is preserved.
5421         start = toFinite(start);
5422         if (end === undefined) {
5423           end = start;
5424           start = 0;
5425         } else {
5426           end = toFinite(end);
5427         }
5428         step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
5429         return baseRange(start, end, step, fromRight);
5430       };
5431     }
5432
5433     /**
5434      * Creates a function that performs a relational operation on two values.
5435      *
5436      * @private
5437      * @param {Function} operator The function to perform the operation.
5438      * @returns {Function} Returns the new relational operation function.
5439      */
5440     function createRelationalOperation(operator) {
5441       return function(value, other) {
5442         if (!(typeof value == 'string' && typeof other == 'string')) {
5443           value = toNumber(value);
5444           other = toNumber(other);
5445         }
5446         return operator(value, other);
5447       };
5448     }
5449
5450     /**
5451      * Creates a function that wraps `func` to continue currying.
5452      *
5453      * @private
5454      * @param {Function} func The function to wrap.
5455      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5456      * @param {Function} wrapFunc The function to create the `func` wrapper.
5457      * @param {*} placeholder The placeholder value.
5458      * @param {*} [thisArg] The `this` binding of `func`.
5459      * @param {Array} [partials] The arguments to prepend to those provided to
5460      *  the new function.
5461      * @param {Array} [holders] The `partials` placeholder indexes.
5462      * @param {Array} [argPos] The argument positions of the new function.
5463      * @param {number} [ary] The arity cap of `func`.
5464      * @param {number} [arity] The arity of `func`.
5465      * @returns {Function} Returns the new wrapped function.
5466      */
5467     function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
5468       var isCurry = bitmask & WRAP_CURRY_FLAG,
5469           newHolders = isCurry ? holders : undefined,
5470           newHoldersRight = isCurry ? undefined : holders,
5471           newPartials = isCurry ? partials : undefined,
5472           newPartialsRight = isCurry ? undefined : partials;
5473
5474       bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
5475       bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
5476
5477       if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
5478         bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
5479       }
5480       var newData = [
5481         func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
5482         newHoldersRight, argPos, ary, arity
5483       ];
5484
5485       var result = wrapFunc.apply(undefined, newData);
5486       if (isLaziable(func)) {
5487         setData(result, newData);
5488       }
5489       result.placeholder = placeholder;
5490       return setWrapToString(result, func, bitmask);
5491     }
5492
5493     /**
5494      * Creates a function like `_.round`.
5495      *
5496      * @private
5497      * @param {string} methodName The name of the `Math` method to use when rounding.
5498      * @returns {Function} Returns the new round function.
5499      */
5500     function createRound(methodName) {
5501       var func = Math[methodName];
5502       return function(number, precision) {
5503         number = toNumber(number);
5504         precision = nativeMin(toInteger(precision), 292);
5505         if (precision) {
5506           // Shift with exponential notation to avoid floating-point issues.
5507           // See [MDN](https://mdn.io/round#Examples) for more details.
5508           var pair = (toString(number) + 'e').split('e'),
5509               value = func(pair[0] + 'e' + (+pair[1] + precision));
5510
5511           pair = (toString(value) + 'e').split('e');
5512           return +(pair[0] + 'e' + (+pair[1] - precision));
5513         }
5514         return func(number);
5515       };
5516     }
5517
5518     /**
5519      * Creates a set object of `values`.
5520      *
5521      * @private
5522      * @param {Array} values The values to add to the set.
5523      * @returns {Object} Returns the new set.
5524      */
5525     var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
5526       return new Set(values);
5527     };
5528
5529     /**
5530      * Creates a `_.toPairs` or `_.toPairsIn` function.
5531      *
5532      * @private
5533      * @param {Function} keysFunc The function to get the keys of a given object.
5534      * @returns {Function} Returns the new pairs function.
5535      */
5536     function createToPairs(keysFunc) {
5537       return function(object) {
5538         var tag = getTag(object);
5539         if (tag == mapTag) {
5540           return mapToArray(object);
5541         }
5542         if (tag == setTag) {
5543           return setToPairs(object);
5544         }
5545         return baseToPairs(object, keysFunc(object));
5546       };
5547     }
5548
5549     /**
5550      * Creates a function that either curries or invokes `func` with optional
5551      * `this` binding and partially applied arguments.
5552      *
5553      * @private
5554      * @param {Function|string} func The function or method name to wrap.
5555      * @param {number} bitmask The bitmask flags.
5556      *    1 - `_.bind`
5557      *    2 - `_.bindKey`
5558      *    4 - `_.curry` or `_.curryRight` of a bound function
5559      *    8 - `_.curry`
5560      *   16 - `_.curryRight`
5561      *   32 - `_.partial`
5562      *   64 - `_.partialRight`
5563      *  128 - `_.rearg`
5564      *  256 - `_.ary`
5565      *  512 - `_.flip`
5566      * @param {*} [thisArg] The `this` binding of `func`.
5567      * @param {Array} [partials] The arguments to be partially applied.
5568      * @param {Array} [holders] The `partials` placeholder indexes.
5569      * @param {Array} [argPos] The argument positions of the new function.
5570      * @param {number} [ary] The arity cap of `func`.
5571      * @param {number} [arity] The arity of `func`.
5572      * @returns {Function} Returns the new wrapped function.
5573      */
5574     function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
5575       var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
5576       if (!isBindKey && typeof func != 'function') {
5577         throw new TypeError(FUNC_ERROR_TEXT);
5578       }
5579       var length = partials ? partials.length : 0;
5580       if (!length) {
5581         bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
5582         partials = holders = undefined;
5583       }
5584       ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
5585       arity = arity === undefined ? arity : toInteger(arity);
5586       length -= holders ? holders.length : 0;
5587
5588       if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
5589         var partialsRight = partials,
5590             holdersRight = holders;
5591
5592         partials = holders = undefined;
5593       }
5594       var data = isBindKey ? undefined : getData(func);
5595
5596       var newData = [
5597         func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
5598         argPos, ary, arity
5599       ];
5600
5601       if (data) {
5602         mergeData(newData, data);
5603       }
5604       func = newData[0];
5605       bitmask = newData[1];
5606       thisArg = newData[2];
5607       partials = newData[3];
5608       holders = newData[4];
5609       arity = newData[9] = newData[9] == null
5610         ? (isBindKey ? 0 : func.length)
5611         : nativeMax(newData[9] - length, 0);
5612
5613       if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
5614         bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
5615       }
5616       if (!bitmask || bitmask == WRAP_BIND_FLAG) {
5617         var result = createBind(func, bitmask, thisArg);
5618       } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
5619         result = createCurry(func, bitmask, arity);
5620       } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
5621         result = createPartial(func, bitmask, thisArg, partials);
5622       } else {
5623         result = createHybrid.apply(undefined, newData);
5624       }
5625       var setter = data ? baseSetData : setData;
5626       return setWrapToString(setter(result, newData), func, bitmask);
5627     }
5628
5629     /**
5630      * A specialized version of `baseIsEqualDeep` for arrays with support for
5631      * partial deep comparisons.
5632      *
5633      * @private
5634      * @param {Array} array The array to compare.
5635      * @param {Array} other The other array to compare.
5636      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5637      * @param {Function} customizer The function to customize comparisons.
5638      * @param {Function} equalFunc The function to determine equivalents of values.
5639      * @param {Object} stack Tracks traversed `array` and `other` objects.
5640      * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
5641      */
5642     function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
5643       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5644           arrLength = array.length,
5645           othLength = other.length;
5646
5647       if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
5648         return false;
5649       }
5650       // Assume cyclic values are equal.
5651       var stacked = stack.get(array);
5652       if (stacked && stack.get(other)) {
5653         return stacked == other;
5654       }
5655       var index = -1,
5656           result = true,
5657           seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
5658
5659       stack.set(array, other);
5660       stack.set(other, array);
5661
5662       // Ignore non-index properties.
5663       while (++index < arrLength) {
5664         var arrValue = array[index],
5665             othValue = other[index];
5666
5667         if (customizer) {
5668           var compared = isPartial
5669             ? customizer(othValue, arrValue, index, other, array, stack)
5670             : customizer(arrValue, othValue, index, array, other, stack);
5671         }
5672         if (compared !== undefined) {
5673           if (compared) {
5674             continue;
5675           }
5676           result = false;
5677           break;
5678         }
5679         // Recursively compare arrays (susceptible to call stack limits).
5680         if (seen) {
5681           if (!arraySome(other, function(othValue, othIndex) {
5682                 if (!cacheHas(seen, othIndex) &&
5683                     (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
5684                   return seen.push(othIndex);
5685                 }
5686               })) {
5687             result = false;
5688             break;
5689           }
5690         } else if (!(
5691               arrValue === othValue ||
5692                 equalFunc(arrValue, othValue, bitmask, customizer, stack)
5693             )) {
5694           result = false;
5695           break;
5696         }
5697       }
5698       stack['delete'](array);
5699       stack['delete'](other);
5700       return result;
5701     }
5702
5703     /**
5704      * A specialized version of `baseIsEqualDeep` for comparing objects of
5705      * the same `toStringTag`.
5706      *
5707      * **Note:** This function only supports comparing values with tags of
5708      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
5709      *
5710      * @private
5711      * @param {Object} object The object to compare.
5712      * @param {Object} other The other object to compare.
5713      * @param {string} tag The `toStringTag` of the objects to compare.
5714      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5715      * @param {Function} customizer The function to customize comparisons.
5716      * @param {Function} equalFunc The function to determine equivalents of values.
5717      * @param {Object} stack Tracks traversed `object` and `other` objects.
5718      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5719      */
5720     function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
5721       switch (tag) {
5722         case dataViewTag:
5723           if ((object.byteLength != other.byteLength) ||
5724               (object.byteOffset != other.byteOffset)) {
5725             return false;
5726           }
5727           object = object.buffer;
5728           other = other.buffer;
5729
5730         case arrayBufferTag:
5731           if ((object.byteLength != other.byteLength) ||
5732               !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
5733             return false;
5734           }
5735           return true;
5736
5737         case boolTag:
5738         case dateTag:
5739         case numberTag:
5740           // Coerce booleans to `1` or `0` and dates to milliseconds.
5741           // Invalid dates are coerced to `NaN`.
5742           return eq(+object, +other);
5743
5744         case errorTag:
5745           return object.name == other.name && object.message == other.message;
5746
5747         case regexpTag:
5748         case stringTag:
5749           // Coerce regexes to strings and treat strings, primitives and objects,
5750           // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
5751           // for more details.
5752           return object == (other + '');
5753
5754         case mapTag:
5755           var convert = mapToArray;
5756
5757         case setTag:
5758           var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
5759           convert || (convert = setToArray);
5760
5761           if (object.size != other.size && !isPartial) {
5762             return false;
5763           }
5764           // Assume cyclic values are equal.
5765           var stacked = stack.get(object);
5766           if (stacked) {
5767             return stacked == other;
5768           }
5769           bitmask |= COMPARE_UNORDERED_FLAG;
5770
5771           // Recursively compare objects (susceptible to call stack limits).
5772           stack.set(object, other);
5773           var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
5774           stack['delete'](object);
5775           return result;
5776
5777         case symbolTag:
5778           if (symbolValueOf) {
5779             return symbolValueOf.call(object) == symbolValueOf.call(other);
5780           }
5781       }
5782       return false;
5783     }
5784
5785     /**
5786      * A specialized version of `baseIsEqualDeep` for objects with support for
5787      * partial deep comparisons.
5788      *
5789      * @private
5790      * @param {Object} object The object to compare.
5791      * @param {Object} other The other object to compare.
5792      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5793      * @param {Function} customizer The function to customize comparisons.
5794      * @param {Function} equalFunc The function to determine equivalents of values.
5795      * @param {Object} stack Tracks traversed `object` and `other` objects.
5796      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5797      */
5798     function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
5799       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5800           objProps = keys(object),
5801           objLength = objProps.length,
5802           othProps = keys(other),
5803           othLength = othProps.length;
5804
5805       if (objLength != othLength && !isPartial) {
5806         return false;
5807       }
5808       var index = objLength;
5809       while (index--) {
5810         var key = objProps[index];
5811         if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
5812           return false;
5813         }
5814       }
5815       // Assume cyclic values are equal.
5816       var stacked = stack.get(object);
5817       if (stacked && stack.get(other)) {
5818         return stacked == other;
5819       }
5820       var result = true;
5821       stack.set(object, other);
5822       stack.set(other, object);
5823
5824       var skipCtor = isPartial;
5825       while (++index < objLength) {
5826         key = objProps[index];
5827         var objValue = object[key],
5828             othValue = other[key];
5829
5830         if (customizer) {
5831           var compared = isPartial
5832             ? customizer(othValue, objValue, key, other, object, stack)
5833             : customizer(objValue, othValue, key, object, other, stack);
5834         }
5835         // Recursively compare objects (susceptible to call stack limits).
5836         if (!(compared === undefined
5837               ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
5838               : compared
5839             )) {
5840           result = false;
5841           break;
5842         }
5843         skipCtor || (skipCtor = key == 'constructor');
5844       }
5845       if (result && !skipCtor) {
5846         var objCtor = object.constructor,
5847             othCtor = other.constructor;
5848
5849         // Non `Object` object instances with different constructors are not equal.
5850         if (objCtor != othCtor &&
5851             ('constructor' in object && 'constructor' in other) &&
5852             !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
5853               typeof othCtor == 'function' && othCtor instanceof othCtor)) {
5854           result = false;
5855         }
5856       }
5857       stack['delete'](object);
5858       stack['delete'](other);
5859       return result;
5860     }
5861
5862     /**
5863      * A specialized version of `baseRest` which flattens the rest array.
5864      *
5865      * @private
5866      * @param {Function} func The function to apply a rest parameter to.
5867      * @returns {Function} Returns the new function.
5868      */
5869     function flatRest(func) {
5870       return setToString(overRest(func, undefined, flatten), func + '');
5871     }
5872
5873     /**
5874      * Creates an array of own enumerable property names and symbols of `object`.
5875      *
5876      * @private
5877      * @param {Object} object The object to query.
5878      * @returns {Array} Returns the array of property names and symbols.
5879      */
5880     function getAllKeys(object) {
5881       return baseGetAllKeys(object, keys, getSymbols);
5882     }
5883
5884     /**
5885      * Creates an array of own and inherited enumerable property names and
5886      * symbols of `object`.
5887      *
5888      * @private
5889      * @param {Object} object The object to query.
5890      * @returns {Array} Returns the array of property names and symbols.
5891      */
5892     function getAllKeysIn(object) {
5893       return baseGetAllKeys(object, keysIn, getSymbolsIn);
5894     }
5895
5896     /**
5897      * Gets metadata for `func`.
5898      *
5899      * @private
5900      * @param {Function} func The function to query.
5901      * @returns {*} Returns the metadata for `func`.
5902      */
5903     var getData = !metaMap ? noop : function(func) {
5904       return metaMap.get(func);
5905     };
5906
5907     /**
5908      * Gets the name of `func`.
5909      *
5910      * @private
5911      * @param {Function} func The function to query.
5912      * @returns {string} Returns the function name.
5913      */
5914     function getFuncName(func) {
5915       var result = (func.name + ''),
5916           array = realNames[result],
5917           length = hasOwnProperty.call(realNames, result) ? array.length : 0;
5918
5919       while (length--) {
5920         var data = array[length],
5921             otherFunc = data.func;
5922         if (otherFunc == null || otherFunc == func) {
5923           return data.name;
5924         }
5925       }
5926       return result;
5927     }
5928
5929     /**
5930      * Gets the argument placeholder value for `func`.
5931      *
5932      * @private
5933      * @param {Function} func The function to inspect.
5934      * @returns {*} Returns the placeholder value.
5935      */
5936     function getHolder(func) {
5937       var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
5938       return object.placeholder;
5939     }
5940
5941     /**
5942      * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
5943      * this function returns the custom method, otherwise it returns `baseIteratee`.
5944      * If arguments are provided, the chosen function is invoked with them and
5945      * its result is returned.
5946      *
5947      * @private
5948      * @param {*} [value] The value to convert to an iteratee.
5949      * @param {number} [arity] The arity of the created iteratee.
5950      * @returns {Function} Returns the chosen function or its result.
5951      */
5952     function getIteratee() {
5953       var result = lodash.iteratee || iteratee;
5954       result = result === iteratee ? baseIteratee : result;
5955       return arguments.length ? result(arguments[0], arguments[1]) : result;
5956     }
5957
5958     /**
5959      * Gets the data for `map`.
5960      *
5961      * @private
5962      * @param {Object} map The map to query.
5963      * @param {string} key The reference key.
5964      * @returns {*} Returns the map data.
5965      */
5966     function getMapData(map, key) {
5967       var data = map.__data__;
5968       return isKeyable(key)
5969         ? data[typeof key == 'string' ? 'string' : 'hash']
5970         : data.map;
5971     }
5972
5973     /**
5974      * Gets the property names, values, and compare flags of `object`.
5975      *
5976      * @private
5977      * @param {Object} object The object to query.
5978      * @returns {Array} Returns the match data of `object`.
5979      */
5980     function getMatchData(object) {
5981       var result = keys(object),
5982           length = result.length;
5983
5984       while (length--) {
5985         var key = result[length],
5986             value = object[key];
5987
5988         result[length] = [key, value, isStrictComparable(value)];
5989       }
5990       return result;
5991     }
5992
5993     /**
5994      * Gets the native function at `key` of `object`.
5995      *
5996      * @private
5997      * @param {Object} object The object to query.
5998      * @param {string} key The key of the method to get.
5999      * @returns {*} Returns the function if it's native, else `undefined`.
6000      */
6001     function getNative(object, key) {
6002       var value = getValue(object, key);
6003       return baseIsNative(value) ? value : undefined;
6004     }
6005
6006     /**
6007      * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
6008      *
6009      * @private
6010      * @param {*} value The value to query.
6011      * @returns {string} Returns the raw `toStringTag`.
6012      */
6013     function getRawTag(value) {
6014       var isOwn = hasOwnProperty.call(value, symToStringTag),
6015           tag = value[symToStringTag];
6016
6017       try {
6018         value[symToStringTag] = undefined;
6019         var unmasked = true;
6020       } catch (e) {}
6021
6022       var result = nativeObjectToString.call(value);
6023       if (unmasked) {
6024         if (isOwn) {
6025           value[symToStringTag] = tag;
6026         } else {
6027           delete value[symToStringTag];
6028         }
6029       }
6030       return result;
6031     }
6032
6033     /**
6034      * Creates an array of the own enumerable symbols of `object`.
6035      *
6036      * @private
6037      * @param {Object} object The object to query.
6038      * @returns {Array} Returns the array of symbols.
6039      */
6040     var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;
6041
6042     /**
6043      * Creates an array of the own and inherited enumerable symbols of `object`.
6044      *
6045      * @private
6046      * @param {Object} object The object to query.
6047      * @returns {Array} Returns the array of symbols.
6048      */
6049     var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
6050       var result = [];
6051       while (object) {
6052         arrayPush(result, getSymbols(object));
6053         object = getPrototype(object);
6054       }
6055       return result;
6056     };
6057
6058     /**
6059      * Gets the `toStringTag` of `value`.
6060      *
6061      * @private
6062      * @param {*} value The value to query.
6063      * @returns {string} Returns the `toStringTag`.
6064      */
6065     var getTag = baseGetTag;
6066
6067     // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
6068     if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
6069         (Map && getTag(new Map) != mapTag) ||
6070         (Promise && getTag(Promise.resolve()) != promiseTag) ||
6071         (Set && getTag(new Set) != setTag) ||
6072         (WeakMap && getTag(new WeakMap) != weakMapTag)) {
6073       getTag = function(value) {
6074         var result = baseGetTag(value),
6075             Ctor = result == objectTag ? value.constructor : undefined,
6076             ctorString = Ctor ? toSource(Ctor) : '';
6077
6078         if (ctorString) {
6079           switch (ctorString) {
6080             case dataViewCtorString: return dataViewTag;
6081             case mapCtorString: return mapTag;
6082             case promiseCtorString: return promiseTag;
6083             case setCtorString: return setTag;
6084             case weakMapCtorString: return weakMapTag;
6085           }
6086         }
6087         return result;
6088       };
6089     }
6090
6091     /**
6092      * Gets the view, applying any `transforms` to the `start` and `end` positions.
6093      *
6094      * @private
6095      * @param {number} start The start of the view.
6096      * @param {number} end The end of the view.
6097      * @param {Array} transforms The transformations to apply to the view.
6098      * @returns {Object} Returns an object containing the `start` and `end`
6099      *  positions of the view.
6100      */
6101     function getView(start, end, transforms) {
6102       var index = -1,
6103           length = transforms.length;
6104
6105       while (++index < length) {
6106         var data = transforms[index],
6107             size = data.size;
6108
6109         switch (data.type) {
6110           case 'drop':      start += size; break;
6111           case 'dropRight': end -= size; break;
6112           case 'take':      end = nativeMin(end, start + size); break;
6113           case 'takeRight': start = nativeMax(start, end - size); break;
6114         }
6115       }
6116       return { 'start': start, 'end': end };
6117     }
6118
6119     /**
6120      * Extracts wrapper details from the `source` body comment.
6121      *
6122      * @private
6123      * @param {string} source The source to inspect.
6124      * @returns {Array} Returns the wrapper details.
6125      */
6126     function getWrapDetails(source) {
6127       var match = source.match(reWrapDetails);
6128       return match ? match[1].split(reSplitDetails) : [];
6129     }
6130
6131     /**
6132      * Checks if `path` exists on `object`.
6133      *
6134      * @private
6135      * @param {Object} object The object to query.
6136      * @param {Array|string} path The path to check.
6137      * @param {Function} hasFunc The function to check properties.
6138      * @returns {boolean} Returns `true` if `path` exists, else `false`.
6139      */
6140     function hasPath(object, path, hasFunc) {
6141       path = castPath(path, object);
6142
6143       var index = -1,
6144           length = path.length,
6145           result = false;
6146
6147       while (++index < length) {
6148         var key = toKey(path[index]);
6149         if (!(result = object != null && hasFunc(object, key))) {
6150           break;
6151         }
6152         object = object[key];
6153       }
6154       if (result || ++index != length) {
6155         return result;
6156       }
6157       length = object == null ? 0 : object.length;
6158       return !!length && isLength(length) && isIndex(key, length) &&
6159         (isArray(object) || isArguments(object));
6160     }
6161
6162     /**
6163      * Initializes an array clone.
6164      *
6165      * @private
6166      * @param {Array} array The array to clone.
6167      * @returns {Array} Returns the initialized clone.
6168      */
6169     function initCloneArray(array) {
6170       var length = array.length,
6171           result = array.constructor(length);
6172
6173       // Add properties assigned by `RegExp#exec`.
6174       if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
6175         result.index = array.index;
6176         result.input = array.input;
6177       }
6178       return result;
6179     }
6180
6181     /**
6182      * Initializes an object clone.
6183      *
6184      * @private
6185      * @param {Object} object The object to clone.
6186      * @returns {Object} Returns the initialized clone.
6187      */
6188     function initCloneObject(object) {
6189       return (typeof object.constructor == 'function' && !isPrototype(object))
6190         ? baseCreate(getPrototype(object))
6191         : {};
6192     }
6193
6194     /**
6195      * Initializes an object clone based on its `toStringTag`.
6196      *
6197      * **Note:** This function only supports cloning values with tags of
6198      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
6199      *
6200      * @private
6201      * @param {Object} object The object to clone.
6202      * @param {string} tag The `toStringTag` of the object to clone.
6203      * @param {Function} cloneFunc The function to clone values.
6204      * @param {boolean} [isDeep] Specify a deep clone.
6205      * @returns {Object} Returns the initialized clone.
6206      */
6207     function initCloneByTag(object, tag, cloneFunc, isDeep) {
6208       var Ctor = object.constructor;
6209       switch (tag) {
6210         case arrayBufferTag:
6211           return cloneArrayBuffer(object);
6212
6213         case boolTag:
6214         case dateTag:
6215           return new Ctor(+object);
6216
6217         case dataViewTag:
6218           return cloneDataView(object, isDeep);
6219
6220         case float32Tag: case float64Tag:
6221         case int8Tag: case int16Tag: case int32Tag:
6222         case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
6223           return cloneTypedArray(object, isDeep);
6224
6225         case mapTag:
6226           return cloneMap(object, isDeep, cloneFunc);
6227
6228         case numberTag:
6229         case stringTag:
6230           return new Ctor(object);
6231
6232         case regexpTag:
6233           return cloneRegExp(object);
6234
6235         case setTag:
6236           return cloneSet(object, isDeep, cloneFunc);
6237
6238         case symbolTag:
6239           return cloneSymbol(object);
6240       }
6241     }
6242
6243     /**
6244      * Inserts wrapper `details` in a comment at the top of the `source` body.
6245      *
6246      * @private
6247      * @param {string} source The source to modify.
6248      * @returns {Array} details The details to insert.
6249      * @returns {string} Returns the modified source.
6250      */
6251     function insertWrapDetails(source, details) {
6252       var length = details.length;
6253       if (!length) {
6254         return source;
6255       }
6256       var lastIndex = length - 1;
6257       details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
6258       details = details.join(length > 2 ? ', ' : ' ');
6259       return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
6260     }
6261
6262     /**
6263      * Checks if `value` is a flattenable `arguments` object or array.
6264      *
6265      * @private
6266      * @param {*} value The value to check.
6267      * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
6268      */
6269     function isFlattenable(value) {
6270       return isArray(value) || isArguments(value) ||
6271         !!(spreadableSymbol && value && value[spreadableSymbol]);
6272     }
6273
6274     /**
6275      * Checks if `value` is a valid array-like index.
6276      *
6277      * @private
6278      * @param {*} value The value to check.
6279      * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
6280      * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
6281      */
6282     function isIndex(value, length) {
6283       length = length == null ? MAX_SAFE_INTEGER : length;
6284       return !!length &&
6285         (typeof value == 'number' || reIsUint.test(value)) &&
6286         (value > -1 && value % 1 == 0 && value < length);
6287     }
6288
6289     /**
6290      * Checks if the given arguments are from an iteratee call.
6291      *
6292      * @private
6293      * @param {*} value The potential iteratee value argument.
6294      * @param {*} index The potential iteratee index or key argument.
6295      * @param {*} object The potential iteratee object argument.
6296      * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
6297      *  else `false`.
6298      */
6299     function isIterateeCall(value, index, object) {
6300       if (!isObject(object)) {
6301         return false;
6302       }
6303       var type = typeof index;
6304       if (type == 'number'
6305             ? (isArrayLike(object) && isIndex(index, object.length))
6306             : (type == 'string' && index in object)
6307           ) {
6308         return eq(object[index], value);
6309       }
6310       return false;
6311     }
6312
6313     /**
6314      * Checks if `value` is a property name and not a property path.
6315      *
6316      * @private
6317      * @param {*} value The value to check.
6318      * @param {Object} [object] The object to query keys on.
6319      * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
6320      */
6321     function isKey(value, object) {
6322       if (isArray(value)) {
6323         return false;
6324       }
6325       var type = typeof value;
6326       if (type == 'number' || type == 'symbol' || type == 'boolean' ||
6327           value == null || isSymbol(value)) {
6328         return true;
6329       }
6330       return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
6331         (object != null && value in Object(object));
6332     }
6333
6334     /**
6335      * Checks if `value` is suitable for use as unique object key.
6336      *
6337      * @private
6338      * @param {*} value The value to check.
6339      * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
6340      */
6341     function isKeyable(value) {
6342       var type = typeof value;
6343       return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
6344         ? (value !== '__proto__')
6345         : (value === null);
6346     }
6347
6348     /**
6349      * Checks if `func` has a lazy counterpart.
6350      *
6351      * @private
6352      * @param {Function} func The function to check.
6353      * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
6354      *  else `false`.
6355      */
6356     function isLaziable(func) {
6357       var funcName = getFuncName(func),
6358           other = lodash[funcName];
6359
6360       if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
6361         return false;
6362       }
6363       if (func === other) {
6364         return true;
6365       }
6366       var data = getData(other);
6367       return !!data && func === data[0];
6368     }
6369
6370     /**
6371      * Checks if `func` has its source masked.
6372      *
6373      * @private
6374      * @param {Function} func The function to check.
6375      * @returns {boolean} Returns `true` if `func` is masked, else `false`.
6376      */
6377     function isMasked(func) {
6378       return !!maskSrcKey && (maskSrcKey in func);
6379     }
6380
6381     /**
6382      * Checks if `func` is capable of being masked.
6383      *
6384      * @private
6385      * @param {*} value The value to check.
6386      * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
6387      */
6388     var isMaskable = coreJsData ? isFunction : stubFalse;
6389
6390     /**
6391      * Checks if `value` is likely a prototype object.
6392      *
6393      * @private
6394      * @param {*} value The value to check.
6395      * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
6396      */
6397     function isPrototype(value) {
6398       var Ctor = value && value.constructor,
6399           proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
6400
6401       return value === proto;
6402     }
6403
6404     /**
6405      * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
6406      *
6407      * @private
6408      * @param {*} value The value to check.
6409      * @returns {boolean} Returns `true` if `value` if suitable for strict
6410      *  equality comparisons, else `false`.
6411      */
6412     function isStrictComparable(value) {
6413       return value === value && !isObject(value);
6414     }
6415
6416     /**
6417      * A specialized version of `matchesProperty` for source values suitable
6418      * for strict equality comparisons, i.e. `===`.
6419      *
6420      * @private
6421      * @param {string} key The key of the property to get.
6422      * @param {*} srcValue The value to match.
6423      * @returns {Function} Returns the new spec function.
6424      */
6425     function matchesStrictComparable(key, srcValue) {
6426       return function(object) {
6427         if (object == null) {
6428           return false;
6429         }
6430         return object[key] === srcValue &&
6431           (srcValue !== undefined || (key in Object(object)));
6432       };
6433     }
6434
6435     /**
6436      * A specialized version of `_.memoize` which clears the memoized function's
6437      * cache when it exceeds `MAX_MEMOIZE_SIZE`.
6438      *
6439      * @private
6440      * @param {Function} func The function to have its output memoized.
6441      * @returns {Function} Returns the new memoized function.
6442      */
6443     function memoizeCapped(func) {
6444       var result = memoize(func, function(key) {
6445         if (cache.size === MAX_MEMOIZE_SIZE) {
6446           cache.clear();
6447         }
6448         return key;
6449       });
6450
6451       var cache = result.cache;
6452       return result;
6453     }
6454
6455     /**
6456      * Merges the function metadata of `source` into `data`.
6457      *
6458      * Merging metadata reduces the number of wrappers used to invoke a function.
6459      * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
6460      * may be applied regardless of execution order. Methods like `_.ary` and
6461      * `_.rearg` modify function arguments, making the order in which they are
6462      * executed important, preventing the merging of metadata. However, we make
6463      * an exception for a safe combined case where curried functions have `_.ary`
6464      * and or `_.rearg` applied.
6465      *
6466      * @private
6467      * @param {Array} data The destination metadata.
6468      * @param {Array} source The source metadata.
6469      * @returns {Array} Returns `data`.
6470      */
6471     function mergeData(data, source) {
6472       var bitmask = data[1],
6473           srcBitmask = source[1],
6474           newBitmask = bitmask | srcBitmask,
6475           isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
6476
6477       var isCombo =
6478         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
6479         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
6480         ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
6481
6482       // Exit early if metadata can't be merged.
6483       if (!(isCommon || isCombo)) {
6484         return data;
6485       }
6486       // Use source `thisArg` if available.
6487       if (srcBitmask & WRAP_BIND_FLAG) {
6488         data[2] = source[2];
6489         // Set when currying a bound function.
6490         newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
6491       }
6492       // Compose partial arguments.
6493       var value = source[3];
6494       if (value) {
6495         var partials = data[3];
6496         data[3] = partials ? composeArgs(partials, value, source[4]) : value;
6497         data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
6498       }
6499       // Compose partial right arguments.
6500       value = source[5];
6501       if (value) {
6502         partials = data[5];
6503         data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
6504         data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
6505       }
6506       // Use source `argPos` if available.
6507       value = source[7];
6508       if (value) {
6509         data[7] = value;
6510       }
6511       // Use source `ary` if it's smaller.
6512       if (srcBitmask & WRAP_ARY_FLAG) {
6513         data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
6514       }
6515       // Use source `arity` if one is not provided.
6516       if (data[9] == null) {
6517         data[9] = source[9];
6518       }
6519       // Use source `func` and merge bitmasks.
6520       data[0] = source[0];
6521       data[1] = newBitmask;
6522
6523       return data;
6524     }
6525
6526     /**
6527      * Used by `_.defaultsDeep` to customize its `_.merge` use.
6528      *
6529      * @private
6530      * @param {*} objValue The destination value.
6531      * @param {*} srcValue The source value.
6532      * @param {string} key The key of the property to merge.
6533      * @param {Object} object The parent object of `objValue`.
6534      * @param {Object} source The parent object of `srcValue`.
6535      * @param {Object} [stack] Tracks traversed source values and their merged
6536      *  counterparts.
6537      * @returns {*} Returns the value to assign.
6538      */
6539     function mergeDefaults(objValue, srcValue, key, object, source, stack) {
6540       if (isObject(objValue) && isObject(srcValue)) {
6541         // Recursively merge objects and arrays (susceptible to call stack limits).
6542         stack.set(srcValue, objValue);
6543         baseMerge(objValue, srcValue, undefined, mergeDefaults, stack);
6544         stack['delete'](srcValue);
6545       }
6546       return objValue;
6547     }
6548
6549     /**
6550      * This function is like
6551      * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
6552      * except that it includes inherited enumerable properties.
6553      *
6554      * @private
6555      * @param {Object} object The object to query.
6556      * @returns {Array} Returns the array of property names.
6557      */
6558     function nativeKeysIn(object) {
6559       var result = [];
6560       if (object != null) {
6561         for (var key in Object(object)) {
6562           result.push(key);
6563         }
6564       }
6565       return result;
6566     }
6567
6568     /**
6569      * Converts `value` to a string using `Object.prototype.toString`.
6570      *
6571      * @private
6572      * @param {*} value The value to convert.
6573      * @returns {string} Returns the converted string.
6574      */
6575     function objectToString(value) {
6576       return nativeObjectToString.call(value);
6577     }
6578
6579     /**
6580      * A specialized version of `baseRest` which transforms the rest array.
6581      *
6582      * @private
6583      * @param {Function} func The function to apply a rest parameter to.
6584      * @param {number} [start=func.length-1] The start position of the rest parameter.
6585      * @param {Function} transform The rest array transform.
6586      * @returns {Function} Returns the new function.
6587      */
6588     function overRest(func, start, transform) {
6589       start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
6590       return function() {
6591         var args = arguments,
6592             index = -1,
6593             length = nativeMax(args.length - start, 0),
6594             array = Array(length);
6595
6596         while (++index < length) {
6597           array[index] = args[start + index];
6598         }
6599         index = -1;
6600         var otherArgs = Array(start + 1);
6601         while (++index < start) {
6602           otherArgs[index] = args[index];
6603         }
6604         otherArgs[start] = transform(array);
6605         return apply(func, this, otherArgs);
6606       };
6607     }
6608
6609     /**
6610      * Gets the parent value at `path` of `object`.
6611      *
6612      * @private
6613      * @param {Object} object The object to query.
6614      * @param {Array} path The path to get the parent value of.
6615      * @returns {*} Returns the parent value.
6616      */
6617     function parent(object, path) {
6618       return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
6619     }
6620
6621     /**
6622      * Reorder `array` according to the specified indexes where the element at
6623      * the first index is assigned as the first element, the element at
6624      * the second index is assigned as the second element, and so on.
6625      *
6626      * @private
6627      * @param {Array} array The array to reorder.
6628      * @param {Array} indexes The arranged array indexes.
6629      * @returns {Array} Returns `array`.
6630      */
6631     function reorder(array, indexes) {
6632       var arrLength = array.length,
6633           length = nativeMin(indexes.length, arrLength),
6634           oldArray = copyArray(array);
6635
6636       while (length--) {
6637         var index = indexes[length];
6638         array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
6639       }
6640       return array;
6641     }
6642
6643     /**
6644      * Sets metadata for `func`.
6645      *
6646      * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
6647      * period of time, it will trip its breaker and transition to an identity
6648      * function to avoid garbage collection pauses in V8. See
6649      * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
6650      * for more details.
6651      *
6652      * @private
6653      * @param {Function} func The function to associate metadata with.
6654      * @param {*} data The metadata.
6655      * @returns {Function} Returns `func`.
6656      */
6657     var setData = shortOut(baseSetData);
6658
6659     /**
6660      * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
6661      *
6662      * @private
6663      * @param {Function} func The function to delay.
6664      * @param {number} wait The number of milliseconds to delay invocation.
6665      * @returns {number|Object} Returns the timer id or timeout object.
6666      */
6667     var setTimeout = ctxSetTimeout || function(func, wait) {
6668       return root.setTimeout(func, wait);
6669     };
6670
6671     /**
6672      * Sets the `toString` method of `func` to return `string`.
6673      *
6674      * @private
6675      * @param {Function} func The function to modify.
6676      * @param {Function} string The `toString` result.
6677      * @returns {Function} Returns `func`.
6678      */
6679     var setToString = shortOut(baseSetToString);
6680
6681     /**
6682      * Sets the `toString` method of `wrapper` to mimic the source of `reference`
6683      * with wrapper details in a comment at the top of the source body.
6684      *
6685      * @private
6686      * @param {Function} wrapper The function to modify.
6687      * @param {Function} reference The reference function.
6688      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6689      * @returns {Function} Returns `wrapper`.
6690      */
6691     function setWrapToString(wrapper, reference, bitmask) {
6692       var source = (reference + '');
6693       return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
6694     }
6695
6696     /**
6697      * Creates a function that'll short out and invoke `identity` instead
6698      * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
6699      * milliseconds.
6700      *
6701      * @private
6702      * @param {Function} func The function to restrict.
6703      * @returns {Function} Returns the new shortable function.
6704      */
6705     function shortOut(func) {
6706       var count = 0,
6707           lastCalled = 0;
6708
6709       return function() {
6710         var stamp = nativeNow(),
6711             remaining = HOT_SPAN - (stamp - lastCalled);
6712
6713         lastCalled = stamp;
6714         if (remaining > 0) {
6715           if (++count >= HOT_COUNT) {
6716             return arguments[0];
6717           }
6718         } else {
6719           count = 0;
6720         }
6721         return func.apply(undefined, arguments);
6722       };
6723     }
6724
6725     /**
6726      * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
6727      *
6728      * @private
6729      * @param {Array} array The array to shuffle.
6730      * @param {number} [size=array.length] The size of `array`.
6731      * @returns {Array} Returns `array`.
6732      */
6733     function shuffleSelf(array, size) {
6734       var index = -1,
6735           length = array.length,
6736           lastIndex = length - 1;
6737
6738       size = size === undefined ? length : size;
6739       while (++index < size) {
6740         var rand = baseRandom(index, lastIndex),
6741             value = array[rand];
6742
6743         array[rand] = array[index];
6744         array[index] = value;
6745       }
6746       array.length = size;
6747       return array;
6748     }
6749
6750     /**
6751      * Converts `string` to a property path array.
6752      *
6753      * @private
6754      * @param {string} string The string to convert.
6755      * @returns {Array} Returns the property path array.
6756      */
6757     var stringToPath = memoizeCapped(function(string) {
6758       var result = [];
6759       if (reLeadingDot.test(string)) {
6760         result.push('');
6761       }
6762       string.replace(rePropName, function(match, number, quote, string) {
6763         result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
6764       });
6765       return result;
6766     });
6767
6768     /**
6769      * Converts `value` to a string key if it's not a string or symbol.
6770      *
6771      * @private
6772      * @param {*} value The value to inspect.
6773      * @returns {string|symbol} Returns the key.
6774      */
6775     function toKey(value) {
6776       if (typeof value == 'string' || isSymbol(value)) {
6777         return value;
6778       }
6779       var result = (value + '');
6780       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
6781     }
6782
6783     /**
6784      * Converts `func` to its source code.
6785      *
6786      * @private
6787      * @param {Function} func The function to convert.
6788      * @returns {string} Returns the source code.
6789      */
6790     function toSource(func) {
6791       if (func != null) {
6792         try {
6793           return funcToString.call(func);
6794         } catch (e) {}
6795         try {
6796           return (func + '');
6797         } catch (e) {}
6798       }
6799       return '';
6800     }
6801
6802     /**
6803      * Updates wrapper `details` based on `bitmask` flags.
6804      *
6805      * @private
6806      * @returns {Array} details The details to modify.
6807      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6808      * @returns {Array} Returns `details`.
6809      */
6810     function updateWrapDetails(details, bitmask) {
6811       arrayEach(wrapFlags, function(pair) {
6812         var value = '_.' + pair[0];
6813         if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
6814           details.push(value);
6815         }
6816       });
6817       return details.sort();
6818     }
6819
6820     /**
6821      * Creates a clone of `wrapper`.
6822      *
6823      * @private
6824      * @param {Object} wrapper The wrapper to clone.
6825      * @returns {Object} Returns the cloned wrapper.
6826      */
6827     function wrapperClone(wrapper) {
6828       if (wrapper instanceof LazyWrapper) {
6829         return wrapper.clone();
6830       }
6831       var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
6832       result.__actions__ = copyArray(wrapper.__actions__);
6833       result.__index__  = wrapper.__index__;
6834       result.__values__ = wrapper.__values__;
6835       return result;
6836     }
6837
6838     /*------------------------------------------------------------------------*/
6839
6840     /**
6841      * Creates an array of elements split into groups the length of `size`.
6842      * If `array` can't be split evenly, the final chunk will be the remaining
6843      * elements.
6844      *
6845      * @static
6846      * @memberOf _
6847      * @since 3.0.0
6848      * @category Array
6849      * @param {Array} array The array to process.
6850      * @param {number} [size=1] The length of each chunk
6851      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
6852      * @returns {Array} Returns the new array of chunks.
6853      * @example
6854      *
6855      * _.chunk(['a', 'b', 'c', 'd'], 2);
6856      * // => [['a', 'b'], ['c', 'd']]
6857      *
6858      * _.chunk(['a', 'b', 'c', 'd'], 3);
6859      * // => [['a', 'b', 'c'], ['d']]
6860      */
6861     function chunk(array, size, guard) {
6862       if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
6863         size = 1;
6864       } else {
6865         size = nativeMax(toInteger(size), 0);
6866       }
6867       var length = array == null ? 0 : array.length;
6868       if (!length || size < 1) {
6869         return [];
6870       }
6871       var index = 0,
6872           resIndex = 0,
6873           result = Array(nativeCeil(length / size));
6874
6875       while (index < length) {
6876         result[resIndex++] = baseSlice(array, index, (index += size));
6877       }
6878       return result;
6879     }
6880
6881     /**
6882      * Creates an array with all falsey values removed. The values `false`, `null`,
6883      * `0`, `""`, `undefined`, and `NaN` are falsey.
6884      *
6885      * @static
6886      * @memberOf _
6887      * @since 0.1.0
6888      * @category Array
6889      * @param {Array} array The array to compact.
6890      * @returns {Array} Returns the new array of filtered values.
6891      * @example
6892      *
6893      * _.compact([0, 1, false, 2, '', 3]);
6894      * // => [1, 2, 3]
6895      */
6896     function compact(array) {
6897       var index = -1,
6898           length = array == null ? 0 : array.length,
6899           resIndex = 0,
6900           result = [];
6901
6902       while (++index < length) {
6903         var value = array[index];
6904         if (value) {
6905           result[resIndex++] = value;
6906         }
6907       }
6908       return result;
6909     }
6910
6911     /**
6912      * Creates a new array concatenating `array` with any additional arrays
6913      * and/or values.
6914      *
6915      * @static
6916      * @memberOf _
6917      * @since 4.0.0
6918      * @category Array
6919      * @param {Array} array The array to concatenate.
6920      * @param {...*} [values] The values to concatenate.
6921      * @returns {Array} Returns the new concatenated array.
6922      * @example
6923      *
6924      * var array = [1];
6925      * var other = _.concat(array, 2, [3], [[4]]);
6926      *
6927      * console.log(other);
6928      * // => [1, 2, 3, [4]]
6929      *
6930      * console.log(array);
6931      * // => [1]
6932      */
6933     function concat() {
6934       var length = arguments.length;
6935       if (!length) {
6936         return [];
6937       }
6938       var args = Array(length - 1),
6939           array = arguments[0],
6940           index = length;
6941
6942       while (index--) {
6943         args[index - 1] = arguments[index];
6944       }
6945       return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
6946     }
6947
6948     /**
6949      * Creates an array of `array` values not included in the other given arrays
6950      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
6951      * for equality comparisons. The order and references of result values are
6952      * determined by the first array.
6953      *
6954      * **Note:** Unlike `_.pullAll`, this method returns a new array.
6955      *
6956      * @static
6957      * @memberOf _
6958      * @since 0.1.0
6959      * @category Array
6960      * @param {Array} array The array to inspect.
6961      * @param {...Array} [values] The values to exclude.
6962      * @returns {Array} Returns the new array of filtered values.
6963      * @see _.without, _.xor
6964      * @example
6965      *
6966      * _.difference([2, 1], [2, 3]);
6967      * // => [1]
6968      */
6969     var difference = baseRest(function(array, values) {
6970       return isArrayLikeObject(array)
6971         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
6972         : [];
6973     });
6974
6975     /**
6976      * This method is like `_.difference` except that it accepts `iteratee` which
6977      * is invoked for each element of `array` and `values` to generate the criterion
6978      * by which they're compared. The order and references of result values are
6979      * determined by the first array. The iteratee is invoked with one argument:
6980      * (value).
6981      *
6982      * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
6983      *
6984      * @static
6985      * @memberOf _
6986      * @since 4.0.0
6987      * @category Array
6988      * @param {Array} array The array to inspect.
6989      * @param {...Array} [values] The values to exclude.
6990      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
6991      * @returns {Array} Returns the new array of filtered values.
6992      * @example
6993      *
6994      * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
6995      * // => [1.2]
6996      *
6997      * // The `_.property` iteratee shorthand.
6998      * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
6999      * // => [{ 'x': 2 }]
7000      */
7001     var differenceBy = baseRest(function(array, values) {
7002       var iteratee = last(values);
7003       if (isArrayLikeObject(iteratee)) {
7004         iteratee = undefined;
7005       }
7006       return isArrayLikeObject(array)
7007         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
7008         : [];
7009     });
7010
7011     /**
7012      * This method is like `_.difference` except that it accepts `comparator`
7013      * which is invoked to compare elements of `array` to `values`. The order and
7014      * references of result values are determined by the first array. The comparator
7015      * is invoked with two arguments: (arrVal, othVal).
7016      *
7017      * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
7018      *
7019      * @static
7020      * @memberOf _
7021      * @since 4.0.0
7022      * @category Array
7023      * @param {Array} array The array to inspect.
7024      * @param {...Array} [values] The values to exclude.
7025      * @param {Function} [comparator] The comparator invoked per element.
7026      * @returns {Array} Returns the new array of filtered values.
7027      * @example
7028      *
7029      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7030      *
7031      * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
7032      * // => [{ 'x': 2, 'y': 1 }]
7033      */
7034     var differenceWith = baseRest(function(array, values) {
7035       var comparator = last(values);
7036       if (isArrayLikeObject(comparator)) {
7037         comparator = undefined;
7038       }
7039       return isArrayLikeObject(array)
7040         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
7041         : [];
7042     });
7043
7044     /**
7045      * Creates a slice of `array` with `n` elements dropped from the beginning.
7046      *
7047      * @static
7048      * @memberOf _
7049      * @since 0.5.0
7050      * @category Array
7051      * @param {Array} array The array to query.
7052      * @param {number} [n=1] The number of elements to drop.
7053      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7054      * @returns {Array} Returns the slice of `array`.
7055      * @example
7056      *
7057      * _.drop([1, 2, 3]);
7058      * // => [2, 3]
7059      *
7060      * _.drop([1, 2, 3], 2);
7061      * // => [3]
7062      *
7063      * _.drop([1, 2, 3], 5);
7064      * // => []
7065      *
7066      * _.drop([1, 2, 3], 0);
7067      * // => [1, 2, 3]
7068      */
7069     function drop(array, n, guard) {
7070       var length = array == null ? 0 : array.length;
7071       if (!length) {
7072         return [];
7073       }
7074       n = (guard || n === undefined) ? 1 : toInteger(n);
7075       return baseSlice(array, n < 0 ? 0 : n, length);
7076     }
7077
7078     /**
7079      * Creates a slice of `array` with `n` elements dropped from the end.
7080      *
7081      * @static
7082      * @memberOf _
7083      * @since 3.0.0
7084      * @category Array
7085      * @param {Array} array The array to query.
7086      * @param {number} [n=1] The number of elements to drop.
7087      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7088      * @returns {Array} Returns the slice of `array`.
7089      * @example
7090      *
7091      * _.dropRight([1, 2, 3]);
7092      * // => [1, 2]
7093      *
7094      * _.dropRight([1, 2, 3], 2);
7095      * // => [1]
7096      *
7097      * _.dropRight([1, 2, 3], 5);
7098      * // => []
7099      *
7100      * _.dropRight([1, 2, 3], 0);
7101      * // => [1, 2, 3]
7102      */
7103     function dropRight(array, n, guard) {
7104       var length = array == null ? 0 : array.length;
7105       if (!length) {
7106         return [];
7107       }
7108       n = (guard || n === undefined) ? 1 : toInteger(n);
7109       n = length - n;
7110       return baseSlice(array, 0, n < 0 ? 0 : n);
7111     }
7112
7113     /**
7114      * Creates a slice of `array` excluding elements dropped from the end.
7115      * Elements are dropped until `predicate` returns falsey. The predicate is
7116      * invoked with three arguments: (value, index, array).
7117      *
7118      * @static
7119      * @memberOf _
7120      * @since 3.0.0
7121      * @category Array
7122      * @param {Array} array The array to query.
7123      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7124      * @returns {Array} Returns the slice of `array`.
7125      * @example
7126      *
7127      * var users = [
7128      *   { 'user': 'barney',  'active': true },
7129      *   { 'user': 'fred',    'active': false },
7130      *   { 'user': 'pebbles', 'active': false }
7131      * ];
7132      *
7133      * _.dropRightWhile(users, function(o) { return !o.active; });
7134      * // => objects for ['barney']
7135      *
7136      * // The `_.matches` iteratee shorthand.
7137      * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
7138      * // => objects for ['barney', 'fred']
7139      *
7140      * // The `_.matchesProperty` iteratee shorthand.
7141      * _.dropRightWhile(users, ['active', false]);
7142      * // => objects for ['barney']
7143      *
7144      * // The `_.property` iteratee shorthand.
7145      * _.dropRightWhile(users, 'active');
7146      * // => objects for ['barney', 'fred', 'pebbles']
7147      */
7148     function dropRightWhile(array, predicate) {
7149       return (array && array.length)
7150         ? baseWhile(array, getIteratee(predicate, 3), true, true)
7151         : [];
7152     }
7153
7154     /**
7155      * Creates a slice of `array` excluding elements dropped from the beginning.
7156      * Elements are dropped until `predicate` returns falsey. The predicate is
7157      * invoked with three arguments: (value, index, array).
7158      *
7159      * @static
7160      * @memberOf _
7161      * @since 3.0.0
7162      * @category Array
7163      * @param {Array} array The array to query.
7164      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7165      * @returns {Array} Returns the slice of `array`.
7166      * @example
7167      *
7168      * var users = [
7169      *   { 'user': 'barney',  'active': false },
7170      *   { 'user': 'fred',    'active': false },
7171      *   { 'user': 'pebbles', 'active': true }
7172      * ];
7173      *
7174      * _.dropWhile(users, function(o) { return !o.active; });
7175      * // => objects for ['pebbles']
7176      *
7177      * // The `_.matches` iteratee shorthand.
7178      * _.dropWhile(users, { 'user': 'barney', 'active': false });
7179      * // => objects for ['fred', 'pebbles']
7180      *
7181      * // The `_.matchesProperty` iteratee shorthand.
7182      * _.dropWhile(users, ['active', false]);
7183      * // => objects for ['pebbles']
7184      *
7185      * // The `_.property` iteratee shorthand.
7186      * _.dropWhile(users, 'active');
7187      * // => objects for ['barney', 'fred', 'pebbles']
7188      */
7189     function dropWhile(array, predicate) {
7190       return (array && array.length)
7191         ? baseWhile(array, getIteratee(predicate, 3), true)
7192         : [];
7193     }
7194
7195     /**
7196      * Fills elements of `array` with `value` from `start` up to, but not
7197      * including, `end`.
7198      *
7199      * **Note:** This method mutates `array`.
7200      *
7201      * @static
7202      * @memberOf _
7203      * @since 3.2.0
7204      * @category Array
7205      * @param {Array} array The array to fill.
7206      * @param {*} value The value to fill `array` with.
7207      * @param {number} [start=0] The start position.
7208      * @param {number} [end=array.length] The end position.
7209      * @returns {Array} Returns `array`.
7210      * @example
7211      *
7212      * var array = [1, 2, 3];
7213      *
7214      * _.fill(array, 'a');
7215      * console.log(array);
7216      * // => ['a', 'a', 'a']
7217      *
7218      * _.fill(Array(3), 2);
7219      * // => [2, 2, 2]
7220      *
7221      * _.fill([4, 6, 8, 10], '*', 1, 3);
7222      * // => [4, '*', '*', 10]
7223      */
7224     function fill(array, value, start, end) {
7225       var length = array == null ? 0 : array.length;
7226       if (!length) {
7227         return [];
7228       }
7229       if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
7230         start = 0;
7231         end = length;
7232       }
7233       return baseFill(array, value, start, end);
7234     }
7235
7236     /**
7237      * This method is like `_.find` except that it returns the index of the first
7238      * element `predicate` returns truthy for instead of the element itself.
7239      *
7240      * @static
7241      * @memberOf _
7242      * @since 1.1.0
7243      * @category Array
7244      * @param {Array} array The array to inspect.
7245      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7246      * @param {number} [fromIndex=0] The index to search from.
7247      * @returns {number} Returns the index of the found element, else `-1`.
7248      * @example
7249      *
7250      * var users = [
7251      *   { 'user': 'barney',  'active': false },
7252      *   { 'user': 'fred',    'active': false },
7253      *   { 'user': 'pebbles', 'active': true }
7254      * ];
7255      *
7256      * _.findIndex(users, function(o) { return o.user == 'barney'; });
7257      * // => 0
7258      *
7259      * // The `_.matches` iteratee shorthand.
7260      * _.findIndex(users, { 'user': 'fred', 'active': false });
7261      * // => 1
7262      *
7263      * // The `_.matchesProperty` iteratee shorthand.
7264      * _.findIndex(users, ['active', false]);
7265      * // => 0
7266      *
7267      * // The `_.property` iteratee shorthand.
7268      * _.findIndex(users, 'active');
7269      * // => 2
7270      */
7271     function findIndex(array, predicate, fromIndex) {
7272       var length = array == null ? 0 : array.length;
7273       if (!length) {
7274         return -1;
7275       }
7276       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7277       if (index < 0) {
7278         index = nativeMax(length + index, 0);
7279       }
7280       return baseFindIndex(array, getIteratee(predicate, 3), index);
7281     }
7282
7283     /**
7284      * This method is like `_.findIndex` except that it iterates over elements
7285      * of `collection` from right to left.
7286      *
7287      * @static
7288      * @memberOf _
7289      * @since 2.0.0
7290      * @category Array
7291      * @param {Array} array The array to inspect.
7292      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7293      * @param {number} [fromIndex=array.length-1] The index to search from.
7294      * @returns {number} Returns the index of the found element, else `-1`.
7295      * @example
7296      *
7297      * var users = [
7298      *   { 'user': 'barney',  'active': true },
7299      *   { 'user': 'fred',    'active': false },
7300      *   { 'user': 'pebbles', 'active': false }
7301      * ];
7302      *
7303      * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
7304      * // => 2
7305      *
7306      * // The `_.matches` iteratee shorthand.
7307      * _.findLastIndex(users, { 'user': 'barney', 'active': true });
7308      * // => 0
7309      *
7310      * // The `_.matchesProperty` iteratee shorthand.
7311      * _.findLastIndex(users, ['active', false]);
7312      * // => 2
7313      *
7314      * // The `_.property` iteratee shorthand.
7315      * _.findLastIndex(users, 'active');
7316      * // => 0
7317      */
7318     function findLastIndex(array, predicate, fromIndex) {
7319       var length = array == null ? 0 : array.length;
7320       if (!length) {
7321         return -1;
7322       }
7323       var index = length - 1;
7324       if (fromIndex !== undefined) {
7325         index = toInteger(fromIndex);
7326         index = fromIndex < 0
7327           ? nativeMax(length + index, 0)
7328           : nativeMin(index, length - 1);
7329       }
7330       return baseFindIndex(array, getIteratee(predicate, 3), index, true);
7331     }
7332
7333     /**
7334      * Flattens `array` a single level deep.
7335      *
7336      * @static
7337      * @memberOf _
7338      * @since 0.1.0
7339      * @category Array
7340      * @param {Array} array The array to flatten.
7341      * @returns {Array} Returns the new flattened array.
7342      * @example
7343      *
7344      * _.flatten([1, [2, [3, [4]], 5]]);
7345      * // => [1, 2, [3, [4]], 5]
7346      */
7347     function flatten(array) {
7348       var length = array == null ? 0 : array.length;
7349       return length ? baseFlatten(array, 1) : [];
7350     }
7351
7352     /**
7353      * Recursively flattens `array`.
7354      *
7355      * @static
7356      * @memberOf _
7357      * @since 3.0.0
7358      * @category Array
7359      * @param {Array} array The array to flatten.
7360      * @returns {Array} Returns the new flattened array.
7361      * @example
7362      *
7363      * _.flattenDeep([1, [2, [3, [4]], 5]]);
7364      * // => [1, 2, 3, 4, 5]
7365      */
7366     function flattenDeep(array) {
7367       var length = array == null ? 0 : array.length;
7368       return length ? baseFlatten(array, INFINITY) : [];
7369     }
7370
7371     /**
7372      * Recursively flatten `array` up to `depth` times.
7373      *
7374      * @static
7375      * @memberOf _
7376      * @since 4.4.0
7377      * @category Array
7378      * @param {Array} array The array to flatten.
7379      * @param {number} [depth=1] The maximum recursion depth.
7380      * @returns {Array} Returns the new flattened array.
7381      * @example
7382      *
7383      * var array = [1, [2, [3, [4]], 5]];
7384      *
7385      * _.flattenDepth(array, 1);
7386      * // => [1, 2, [3, [4]], 5]
7387      *
7388      * _.flattenDepth(array, 2);
7389      * // => [1, 2, 3, [4], 5]
7390      */
7391     function flattenDepth(array, depth) {
7392       var length = array == null ? 0 : array.length;
7393       if (!length) {
7394         return [];
7395       }
7396       depth = depth === undefined ? 1 : toInteger(depth);
7397       return baseFlatten(array, depth);
7398     }
7399
7400     /**
7401      * The inverse of `_.toPairs`; this method returns an object composed
7402      * from key-value `pairs`.
7403      *
7404      * @static
7405      * @memberOf _
7406      * @since 4.0.0
7407      * @category Array
7408      * @param {Array} pairs The key-value pairs.
7409      * @returns {Object} Returns the new object.
7410      * @example
7411      *
7412      * _.fromPairs([['a', 1], ['b', 2]]);
7413      * // => { 'a': 1, 'b': 2 }
7414      */
7415     function fromPairs(pairs) {
7416       var index = -1,
7417           length = pairs == null ? 0 : pairs.length,
7418           result = {};
7419
7420       while (++index < length) {
7421         var pair = pairs[index];
7422         result[pair[0]] = pair[1];
7423       }
7424       return result;
7425     }
7426
7427     /**
7428      * Gets the first element of `array`.
7429      *
7430      * @static
7431      * @memberOf _
7432      * @since 0.1.0
7433      * @alias first
7434      * @category Array
7435      * @param {Array} array The array to query.
7436      * @returns {*} Returns the first element of `array`.
7437      * @example
7438      *
7439      * _.head([1, 2, 3]);
7440      * // => 1
7441      *
7442      * _.head([]);
7443      * // => undefined
7444      */
7445     function head(array) {
7446       return (array && array.length) ? array[0] : undefined;
7447     }
7448
7449     /**
7450      * Gets the index at which the first occurrence of `value` is found in `array`
7451      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7452      * for equality comparisons. If `fromIndex` is negative, it's used as the
7453      * offset from the end of `array`.
7454      *
7455      * @static
7456      * @memberOf _
7457      * @since 0.1.0
7458      * @category Array
7459      * @param {Array} array The array to inspect.
7460      * @param {*} value The value to search for.
7461      * @param {number} [fromIndex=0] The index to search from.
7462      * @returns {number} Returns the index of the matched value, else `-1`.
7463      * @example
7464      *
7465      * _.indexOf([1, 2, 1, 2], 2);
7466      * // => 1
7467      *
7468      * // Search from the `fromIndex`.
7469      * _.indexOf([1, 2, 1, 2], 2, 2);
7470      * // => 3
7471      */
7472     function indexOf(array, value, fromIndex) {
7473       var length = array == null ? 0 : array.length;
7474       if (!length) {
7475         return -1;
7476       }
7477       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7478       if (index < 0) {
7479         index = nativeMax(length + index, 0);
7480       }
7481       return baseIndexOf(array, value, index);
7482     }
7483
7484     /**
7485      * Gets all but the last element of `array`.
7486      *
7487      * @static
7488      * @memberOf _
7489      * @since 0.1.0
7490      * @category Array
7491      * @param {Array} array The array to query.
7492      * @returns {Array} Returns the slice of `array`.
7493      * @example
7494      *
7495      * _.initial([1, 2, 3]);
7496      * // => [1, 2]
7497      */
7498     function initial(array) {
7499       var length = array == null ? 0 : array.length;
7500       return length ? baseSlice(array, 0, -1) : [];
7501     }
7502
7503     /**
7504      * Creates an array of unique values that are included in all given arrays
7505      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7506      * for equality comparisons. The order and references of result values are
7507      * determined by the first array.
7508      *
7509      * @static
7510      * @memberOf _
7511      * @since 0.1.0
7512      * @category Array
7513      * @param {...Array} [arrays] The arrays to inspect.
7514      * @returns {Array} Returns the new array of intersecting values.
7515      * @example
7516      *
7517      * _.intersection([2, 1], [2, 3]);
7518      * // => [2]
7519      */
7520     var intersection = baseRest(function(arrays) {
7521       var mapped = arrayMap(arrays, castArrayLikeObject);
7522       return (mapped.length && mapped[0] === arrays[0])
7523         ? baseIntersection(mapped)
7524         : [];
7525     });
7526
7527     /**
7528      * This method is like `_.intersection` except that it accepts `iteratee`
7529      * which is invoked for each element of each `arrays` to generate the criterion
7530      * by which they're compared. The order and references of result values are
7531      * determined by the first array. The iteratee is invoked with one argument:
7532      * (value).
7533      *
7534      * @static
7535      * @memberOf _
7536      * @since 4.0.0
7537      * @category Array
7538      * @param {...Array} [arrays] The arrays to inspect.
7539      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7540      * @returns {Array} Returns the new array of intersecting values.
7541      * @example
7542      *
7543      * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7544      * // => [2.1]
7545      *
7546      * // The `_.property` iteratee shorthand.
7547      * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
7548      * // => [{ 'x': 1 }]
7549      */
7550     var intersectionBy = baseRest(function(arrays) {
7551       var iteratee = last(arrays),
7552           mapped = arrayMap(arrays, castArrayLikeObject);
7553
7554       if (iteratee === last(mapped)) {
7555         iteratee = undefined;
7556       } else {
7557         mapped.pop();
7558       }
7559       return (mapped.length && mapped[0] === arrays[0])
7560         ? baseIntersection(mapped, getIteratee(iteratee, 2))
7561         : [];
7562     });
7563
7564     /**
7565      * This method is like `_.intersection` except that it accepts `comparator`
7566      * which is invoked to compare elements of `arrays`. The order and references
7567      * of result values are determined by the first array. The comparator is
7568      * invoked with two arguments: (arrVal, othVal).
7569      *
7570      * @static
7571      * @memberOf _
7572      * @since 4.0.0
7573      * @category Array
7574      * @param {...Array} [arrays] The arrays to inspect.
7575      * @param {Function} [comparator] The comparator invoked per element.
7576      * @returns {Array} Returns the new array of intersecting values.
7577      * @example
7578      *
7579      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7580      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
7581      *
7582      * _.intersectionWith(objects, others, _.isEqual);
7583      * // => [{ 'x': 1, 'y': 2 }]
7584      */
7585     var intersectionWith = baseRest(function(arrays) {
7586       var comparator = last(arrays),
7587           mapped = arrayMap(arrays, castArrayLikeObject);
7588
7589       comparator = typeof comparator == 'function' ? comparator : undefined;
7590       if (comparator) {
7591         mapped.pop();
7592       }
7593       return (mapped.length && mapped[0] === arrays[0])
7594         ? baseIntersection(mapped, undefined, comparator)
7595         : [];
7596     });
7597
7598     /**
7599      * Converts all elements in `array` into a string separated by `separator`.
7600      *
7601      * @static
7602      * @memberOf _
7603      * @since 4.0.0
7604      * @category Array
7605      * @param {Array} array The array to convert.
7606      * @param {string} [separator=','] The element separator.
7607      * @returns {string} Returns the joined string.
7608      * @example
7609      *
7610      * _.join(['a', 'b', 'c'], '~');
7611      * // => 'a~b~c'
7612      */
7613     function join(array, separator) {
7614       return array == null ? '' : nativeJoin.call(array, separator);
7615     }
7616
7617     /**
7618      * Gets the last element of `array`.
7619      *
7620      * @static
7621      * @memberOf _
7622      * @since 0.1.0
7623      * @category Array
7624      * @param {Array} array The array to query.
7625      * @returns {*} Returns the last element of `array`.
7626      * @example
7627      *
7628      * _.last([1, 2, 3]);
7629      * // => 3
7630      */
7631     function last(array) {
7632       var length = array == null ? 0 : array.length;
7633       return length ? array[length - 1] : undefined;
7634     }
7635
7636     /**
7637      * This method is like `_.indexOf` except that it iterates over elements of
7638      * `array` from right to left.
7639      *
7640      * @static
7641      * @memberOf _
7642      * @since 0.1.0
7643      * @category Array
7644      * @param {Array} array The array to inspect.
7645      * @param {*} value The value to search for.
7646      * @param {number} [fromIndex=array.length-1] The index to search from.
7647      * @returns {number} Returns the index of the matched value, else `-1`.
7648      * @example
7649      *
7650      * _.lastIndexOf([1, 2, 1, 2], 2);
7651      * // => 3
7652      *
7653      * // Search from the `fromIndex`.
7654      * _.lastIndexOf([1, 2, 1, 2], 2, 2);
7655      * // => 1
7656      */
7657     function lastIndexOf(array, value, fromIndex) {
7658       var length = array == null ? 0 : array.length;
7659       if (!length) {
7660         return -1;
7661       }
7662       var index = length;
7663       if (fromIndex !== undefined) {
7664         index = toInteger(fromIndex);
7665         index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
7666       }
7667       return value === value
7668         ? strictLastIndexOf(array, value, index)
7669         : baseFindIndex(array, baseIsNaN, index, true);
7670     }
7671
7672     /**
7673      * Gets the element at index `n` of `array`. If `n` is negative, the nth
7674      * element from the end is returned.
7675      *
7676      * @static
7677      * @memberOf _
7678      * @since 4.11.0
7679      * @category Array
7680      * @param {Array} array The array to query.
7681      * @param {number} [n=0] The index of the element to return.
7682      * @returns {*} Returns the nth element of `array`.
7683      * @example
7684      *
7685      * var array = ['a', 'b', 'c', 'd'];
7686      *
7687      * _.nth(array, 1);
7688      * // => 'b'
7689      *
7690      * _.nth(array, -2);
7691      * // => 'c';
7692      */
7693     function nth(array, n) {
7694       return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
7695     }
7696
7697     /**
7698      * Removes all given values from `array` using
7699      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7700      * for equality comparisons.
7701      *
7702      * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
7703      * to remove elements from an array by predicate.
7704      *
7705      * @static
7706      * @memberOf _
7707      * @since 2.0.0
7708      * @category Array
7709      * @param {Array} array The array to modify.
7710      * @param {...*} [values] The values to remove.
7711      * @returns {Array} Returns `array`.
7712      * @example
7713      *
7714      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7715      *
7716      * _.pull(array, 'a', 'c');
7717      * console.log(array);
7718      * // => ['b', 'b']
7719      */
7720     var pull = baseRest(pullAll);
7721
7722     /**
7723      * This method is like `_.pull` except that it accepts an array of values to remove.
7724      *
7725      * **Note:** Unlike `_.difference`, this method mutates `array`.
7726      *
7727      * @static
7728      * @memberOf _
7729      * @since 4.0.0
7730      * @category Array
7731      * @param {Array} array The array to modify.
7732      * @param {Array} values The values to remove.
7733      * @returns {Array} Returns `array`.
7734      * @example
7735      *
7736      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7737      *
7738      * _.pullAll(array, ['a', 'c']);
7739      * console.log(array);
7740      * // => ['b', 'b']
7741      */
7742     function pullAll(array, values) {
7743       return (array && array.length && values && values.length)
7744         ? basePullAll(array, values)
7745         : array;
7746     }
7747
7748     /**
7749      * This method is like `_.pullAll` except that it accepts `iteratee` which is
7750      * invoked for each element of `array` and `values` to generate the criterion
7751      * by which they're compared. The iteratee is invoked with one argument: (value).
7752      *
7753      * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
7754      *
7755      * @static
7756      * @memberOf _
7757      * @since 4.0.0
7758      * @category Array
7759      * @param {Array} array The array to modify.
7760      * @param {Array} values The values to remove.
7761      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7762      * @returns {Array} Returns `array`.
7763      * @example
7764      *
7765      * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
7766      *
7767      * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
7768      * console.log(array);
7769      * // => [{ 'x': 2 }]
7770      */
7771     function pullAllBy(array, values, iteratee) {
7772       return (array && array.length && values && values.length)
7773         ? basePullAll(array, values, getIteratee(iteratee, 2))
7774         : array;
7775     }
7776
7777     /**
7778      * This method is like `_.pullAll` except that it accepts `comparator` which
7779      * is invoked to compare elements of `array` to `values`. The comparator is
7780      * invoked with two arguments: (arrVal, othVal).
7781      *
7782      * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
7783      *
7784      * @static
7785      * @memberOf _
7786      * @since 4.6.0
7787      * @category Array
7788      * @param {Array} array The array to modify.
7789      * @param {Array} values The values to remove.
7790      * @param {Function} [comparator] The comparator invoked per element.
7791      * @returns {Array} Returns `array`.
7792      * @example
7793      *
7794      * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
7795      *
7796      * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
7797      * console.log(array);
7798      * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
7799      */
7800     function pullAllWith(array, values, comparator) {
7801       return (array && array.length && values && values.length)
7802         ? basePullAll(array, values, undefined, comparator)
7803         : array;
7804     }
7805
7806     /**
7807      * Removes elements from `array` corresponding to `indexes` and returns an
7808      * array of removed elements.
7809      *
7810      * **Note:** Unlike `_.at`, this method mutates `array`.
7811      *
7812      * @static
7813      * @memberOf _
7814      * @since 3.0.0
7815      * @category Array
7816      * @param {Array} array The array to modify.
7817      * @param {...(number|number[])} [indexes] The indexes of elements to remove.
7818      * @returns {Array} Returns the new array of removed elements.
7819      * @example
7820      *
7821      * var array = ['a', 'b', 'c', 'd'];
7822      * var pulled = _.pullAt(array, [1, 3]);
7823      *
7824      * console.log(array);
7825      * // => ['a', 'c']
7826      *
7827      * console.log(pulled);
7828      * // => ['b', 'd']
7829      */
7830     var pullAt = flatRest(function(array, indexes) {
7831       var length = array == null ? 0 : array.length,
7832           result = baseAt(array, indexes);
7833
7834       basePullAt(array, arrayMap(indexes, function(index) {
7835         return isIndex(index, length) ? +index : index;
7836       }).sort(compareAscending));
7837
7838       return result;
7839     });
7840
7841     /**
7842      * Removes all elements from `array` that `predicate` returns truthy for
7843      * and returns an array of the removed elements. The predicate is invoked
7844      * with three arguments: (value, index, array).
7845      *
7846      * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
7847      * to pull elements from an array by value.
7848      *
7849      * @static
7850      * @memberOf _
7851      * @since 2.0.0
7852      * @category Array
7853      * @param {Array} array The array to modify.
7854      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7855      * @returns {Array} Returns the new array of removed elements.
7856      * @example
7857      *
7858      * var array = [1, 2, 3, 4];
7859      * var evens = _.remove(array, function(n) {
7860      *   return n % 2 == 0;
7861      * });
7862      *
7863      * console.log(array);
7864      * // => [1, 3]
7865      *
7866      * console.log(evens);
7867      * // => [2, 4]
7868      */
7869     function remove(array, predicate) {
7870       var result = [];
7871       if (!(array && array.length)) {
7872         return result;
7873       }
7874       var index = -1,
7875           indexes = [],
7876           length = array.length;
7877
7878       predicate = getIteratee(predicate, 3);
7879       while (++index < length) {
7880         var value = array[index];
7881         if (predicate(value, index, array)) {
7882           result.push(value);
7883           indexes.push(index);
7884         }
7885       }
7886       basePullAt(array, indexes);
7887       return result;
7888     }
7889
7890     /**
7891      * Reverses `array` so that the first element becomes the last, the second
7892      * element becomes the second to last, and so on.
7893      *
7894      * **Note:** This method mutates `array` and is based on
7895      * [`Array#reverse`](https://mdn.io/Array/reverse).
7896      *
7897      * @static
7898      * @memberOf _
7899      * @since 4.0.0
7900      * @category Array
7901      * @param {Array} array The array to modify.
7902      * @returns {Array} Returns `array`.
7903      * @example
7904      *
7905      * var array = [1, 2, 3];
7906      *
7907      * _.reverse(array);
7908      * // => [3, 2, 1]
7909      *
7910      * console.log(array);
7911      * // => [3, 2, 1]
7912      */
7913     function reverse(array) {
7914       return array == null ? array : nativeReverse.call(array);
7915     }
7916
7917     /**
7918      * Creates a slice of `array` from `start` up to, but not including, `end`.
7919      *
7920      * **Note:** This method is used instead of
7921      * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
7922      * returned.
7923      *
7924      * @static
7925      * @memberOf _
7926      * @since 3.0.0
7927      * @category Array
7928      * @param {Array} array The array to slice.
7929      * @param {number} [start=0] The start position.
7930      * @param {number} [end=array.length] The end position.
7931      * @returns {Array} Returns the slice of `array`.
7932      */
7933     function slice(array, start, end) {
7934       var length = array == null ? 0 : array.length;
7935       if (!length) {
7936         return [];
7937       }
7938       if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
7939         start = 0;
7940         end = length;
7941       }
7942       else {
7943         start = start == null ? 0 : toInteger(start);
7944         end = end === undefined ? length : toInteger(end);
7945       }
7946       return baseSlice(array, start, end);
7947     }
7948
7949     /**
7950      * Uses a binary search to determine the lowest index at which `value`
7951      * should be inserted into `array` in order to maintain its sort order.
7952      *
7953      * @static
7954      * @memberOf _
7955      * @since 0.1.0
7956      * @category Array
7957      * @param {Array} array The sorted array to inspect.
7958      * @param {*} value The value to evaluate.
7959      * @returns {number} Returns the index at which `value` should be inserted
7960      *  into `array`.
7961      * @example
7962      *
7963      * _.sortedIndex([30, 50], 40);
7964      * // => 1
7965      */
7966     function sortedIndex(array, value) {
7967       return baseSortedIndex(array, value);
7968     }
7969
7970     /**
7971      * This method is like `_.sortedIndex` except that it accepts `iteratee`
7972      * which is invoked for `value` and each element of `array` to compute their
7973      * sort ranking. The iteratee is invoked with one argument: (value).
7974      *
7975      * @static
7976      * @memberOf _
7977      * @since 4.0.0
7978      * @category Array
7979      * @param {Array} array The sorted array to inspect.
7980      * @param {*} value The value to evaluate.
7981      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7982      * @returns {number} Returns the index at which `value` should be inserted
7983      *  into `array`.
7984      * @example
7985      *
7986      * var objects = [{ 'x': 4 }, { 'x': 5 }];
7987      *
7988      * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
7989      * // => 0
7990      *
7991      * // The `_.property` iteratee shorthand.
7992      * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
7993      * // => 0
7994      */
7995     function sortedIndexBy(array, value, iteratee) {
7996       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
7997     }
7998
7999     /**
8000      * This method is like `_.indexOf` except that it performs a binary
8001      * search on a sorted `array`.
8002      *
8003      * @static
8004      * @memberOf _
8005      * @since 4.0.0
8006      * @category Array
8007      * @param {Array} array The array to inspect.
8008      * @param {*} value The value to search for.
8009      * @returns {number} Returns the index of the matched value, else `-1`.
8010      * @example
8011      *
8012      * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
8013      * // => 1
8014      */
8015     function sortedIndexOf(array, value) {
8016       var length = array == null ? 0 : array.length;
8017       if (length) {
8018         var index = baseSortedIndex(array, value);
8019         if (index < length && eq(array[index], value)) {
8020           return index;
8021         }
8022       }
8023       return -1;
8024     }
8025
8026     /**
8027      * This method is like `_.sortedIndex` except that it returns the highest
8028      * index at which `value` should be inserted into `array` in order to
8029      * maintain its sort order.
8030      *
8031      * @static
8032      * @memberOf _
8033      * @since 3.0.0
8034      * @category Array
8035      * @param {Array} array The sorted array to inspect.
8036      * @param {*} value The value to evaluate.
8037      * @returns {number} Returns the index at which `value` should be inserted
8038      *  into `array`.
8039      * @example
8040      *
8041      * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
8042      * // => 4
8043      */
8044     function sortedLastIndex(array, value) {
8045       return baseSortedIndex(array, value, true);
8046     }
8047
8048     /**
8049      * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
8050      * which is invoked for `value` and each element of `array` to compute their
8051      * sort ranking. The iteratee is invoked with one argument: (value).
8052      *
8053      * @static
8054      * @memberOf _
8055      * @since 4.0.0
8056      * @category Array
8057      * @param {Array} array The sorted array to inspect.
8058      * @param {*} value The value to evaluate.
8059      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8060      * @returns {number} Returns the index at which `value` should be inserted
8061      *  into `array`.
8062      * @example
8063      *
8064      * var objects = [{ 'x': 4 }, { 'x': 5 }];
8065      *
8066      * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8067      * // => 1
8068      *
8069      * // The `_.property` iteratee shorthand.
8070      * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
8071      * // => 1
8072      */
8073     function sortedLastIndexBy(array, value, iteratee) {
8074       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
8075     }
8076
8077     /**
8078      * This method is like `_.lastIndexOf` except that it performs a binary
8079      * search on a sorted `array`.
8080      *
8081      * @static
8082      * @memberOf _
8083      * @since 4.0.0
8084      * @category Array
8085      * @param {Array} array The array to inspect.
8086      * @param {*} value The value to search for.
8087      * @returns {number} Returns the index of the matched value, else `-1`.
8088      * @example
8089      *
8090      * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
8091      * // => 3
8092      */
8093     function sortedLastIndexOf(array, value) {
8094       var length = array == null ? 0 : array.length;
8095       if (length) {
8096         var index = baseSortedIndex(array, value, true) - 1;
8097         if (eq(array[index], value)) {
8098           return index;
8099         }
8100       }
8101       return -1;
8102     }
8103
8104     /**
8105      * This method is like `_.uniq` except that it's designed and optimized
8106      * for sorted arrays.
8107      *
8108      * @static
8109      * @memberOf _
8110      * @since 4.0.0
8111      * @category Array
8112      * @param {Array} array The array to inspect.
8113      * @returns {Array} Returns the new duplicate free array.
8114      * @example
8115      *
8116      * _.sortedUniq([1, 1, 2]);
8117      * // => [1, 2]
8118      */
8119     function sortedUniq(array) {
8120       return (array && array.length)
8121         ? baseSortedUniq(array)
8122         : [];
8123     }
8124
8125     /**
8126      * This method is like `_.uniqBy` except that it's designed and optimized
8127      * for sorted arrays.
8128      *
8129      * @static
8130      * @memberOf _
8131      * @since 4.0.0
8132      * @category Array
8133      * @param {Array} array The array to inspect.
8134      * @param {Function} [iteratee] The iteratee invoked per element.
8135      * @returns {Array} Returns the new duplicate free array.
8136      * @example
8137      *
8138      * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
8139      * // => [1.1, 2.3]
8140      */
8141     function sortedUniqBy(array, iteratee) {
8142       return (array && array.length)
8143         ? baseSortedUniq(array, getIteratee(iteratee, 2))
8144         : [];
8145     }
8146
8147     /**
8148      * Gets all but the first element of `array`.
8149      *
8150      * @static
8151      * @memberOf _
8152      * @since 4.0.0
8153      * @category Array
8154      * @param {Array} array The array to query.
8155      * @returns {Array} Returns the slice of `array`.
8156      * @example
8157      *
8158      * _.tail([1, 2, 3]);
8159      * // => [2, 3]
8160      */
8161     function tail(array) {
8162       var length = array == null ? 0 : array.length;
8163       return length ? baseSlice(array, 1, length) : [];
8164     }
8165
8166     /**
8167      * Creates a slice of `array` with `n` elements taken from the beginning.
8168      *
8169      * @static
8170      * @memberOf _
8171      * @since 0.1.0
8172      * @category Array
8173      * @param {Array} array The array to query.
8174      * @param {number} [n=1] The number of elements to take.
8175      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8176      * @returns {Array} Returns the slice of `array`.
8177      * @example
8178      *
8179      * _.take([1, 2, 3]);
8180      * // => [1]
8181      *
8182      * _.take([1, 2, 3], 2);
8183      * // => [1, 2]
8184      *
8185      * _.take([1, 2, 3], 5);
8186      * // => [1, 2, 3]
8187      *
8188      * _.take([1, 2, 3], 0);
8189      * // => []
8190      */
8191     function take(array, n, guard) {
8192       if (!(array && array.length)) {
8193         return [];
8194       }
8195       n = (guard || n === undefined) ? 1 : toInteger(n);
8196       return baseSlice(array, 0, n < 0 ? 0 : n);
8197     }
8198
8199     /**
8200      * Creates a slice of `array` with `n` elements taken from the end.
8201      *
8202      * @static
8203      * @memberOf _
8204      * @since 3.0.0
8205      * @category Array
8206      * @param {Array} array The array to query.
8207      * @param {number} [n=1] The number of elements to take.
8208      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8209      * @returns {Array} Returns the slice of `array`.
8210      * @example
8211      *
8212      * _.takeRight([1, 2, 3]);
8213      * // => [3]
8214      *
8215      * _.takeRight([1, 2, 3], 2);
8216      * // => [2, 3]
8217      *
8218      * _.takeRight([1, 2, 3], 5);
8219      * // => [1, 2, 3]
8220      *
8221      * _.takeRight([1, 2, 3], 0);
8222      * // => []
8223      */
8224     function takeRight(array, n, guard) {
8225       var length = array == null ? 0 : array.length;
8226       if (!length) {
8227         return [];
8228       }
8229       n = (guard || n === undefined) ? 1 : toInteger(n);
8230       n = length - n;
8231       return baseSlice(array, n < 0 ? 0 : n, length);
8232     }
8233
8234     /**
8235      * Creates a slice of `array` with elements taken from the end. Elements are
8236      * taken until `predicate` returns falsey. The predicate is invoked with
8237      * three arguments: (value, index, array).
8238      *
8239      * @static
8240      * @memberOf _
8241      * @since 3.0.0
8242      * @category Array
8243      * @param {Array} array The array to query.
8244      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8245      * @returns {Array} Returns the slice of `array`.
8246      * @example
8247      *
8248      * var users = [
8249      *   { 'user': 'barney',  'active': true },
8250      *   { 'user': 'fred',    'active': false },
8251      *   { 'user': 'pebbles', 'active': false }
8252      * ];
8253      *
8254      * _.takeRightWhile(users, function(o) { return !o.active; });
8255      * // => objects for ['fred', 'pebbles']
8256      *
8257      * // The `_.matches` iteratee shorthand.
8258      * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
8259      * // => objects for ['pebbles']
8260      *
8261      * // The `_.matchesProperty` iteratee shorthand.
8262      * _.takeRightWhile(users, ['active', false]);
8263      * // => objects for ['fred', 'pebbles']
8264      *
8265      * // The `_.property` iteratee shorthand.
8266      * _.takeRightWhile(users, 'active');
8267      * // => []
8268      */
8269     function takeRightWhile(array, predicate) {
8270       return (array && array.length)
8271         ? baseWhile(array, getIteratee(predicate, 3), false, true)
8272         : [];
8273     }
8274
8275     /**
8276      * Creates a slice of `array` with elements taken from the beginning. Elements
8277      * are taken until `predicate` returns falsey. The predicate is invoked with
8278      * three arguments: (value, index, array).
8279      *
8280      * @static
8281      * @memberOf _
8282      * @since 3.0.0
8283      * @category Array
8284      * @param {Array} array The array to query.
8285      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8286      * @returns {Array} Returns the slice of `array`.
8287      * @example
8288      *
8289      * var users = [
8290      *   { 'user': 'barney',  'active': false },
8291      *   { 'user': 'fred',    'active': false},
8292      *   { 'user': 'pebbles', 'active': true }
8293      * ];
8294      *
8295      * _.takeWhile(users, function(o) { return !o.active; });
8296      * // => objects for ['barney', 'fred']
8297      *
8298      * // The `_.matches` iteratee shorthand.
8299      * _.takeWhile(users, { 'user': 'barney', 'active': false });
8300      * // => objects for ['barney']
8301      *
8302      * // The `_.matchesProperty` iteratee shorthand.
8303      * _.takeWhile(users, ['active', false]);
8304      * // => objects for ['barney', 'fred']
8305      *
8306      * // The `_.property` iteratee shorthand.
8307      * _.takeWhile(users, 'active');
8308      * // => []
8309      */
8310     function takeWhile(array, predicate) {
8311       return (array && array.length)
8312         ? baseWhile(array, getIteratee(predicate, 3))
8313         : [];
8314     }
8315
8316     /**
8317      * Creates an array of unique values, in order, from all given arrays using
8318      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8319      * for equality comparisons.
8320      *
8321      * @static
8322      * @memberOf _
8323      * @since 0.1.0
8324      * @category Array
8325      * @param {...Array} [arrays] The arrays to inspect.
8326      * @returns {Array} Returns the new array of combined values.
8327      * @example
8328      *
8329      * _.union([2], [1, 2]);
8330      * // => [2, 1]
8331      */
8332     var union = baseRest(function(arrays) {
8333       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
8334     });
8335
8336     /**
8337      * This method is like `_.union` except that it accepts `iteratee` which is
8338      * invoked for each element of each `arrays` to generate the criterion by
8339      * which uniqueness is computed. Result values are chosen from the first
8340      * array in which the value occurs. The iteratee is invoked with one argument:
8341      * (value).
8342      *
8343      * @static
8344      * @memberOf _
8345      * @since 4.0.0
8346      * @category Array
8347      * @param {...Array} [arrays] The arrays to inspect.
8348      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8349      * @returns {Array} Returns the new array of combined values.
8350      * @example
8351      *
8352      * _.unionBy([2.1], [1.2, 2.3], Math.floor);
8353      * // => [2.1, 1.2]
8354      *
8355      * // The `_.property` iteratee shorthand.
8356      * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8357      * // => [{ 'x': 1 }, { 'x': 2 }]
8358      */
8359     var unionBy = baseRest(function(arrays) {
8360       var iteratee = last(arrays);
8361       if (isArrayLikeObject(iteratee)) {
8362         iteratee = undefined;
8363       }
8364       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
8365     });
8366
8367     /**
8368      * This method is like `_.union` except that it accepts `comparator` which
8369      * is invoked to compare elements of `arrays`. Result values are chosen from
8370      * the first array in which the value occurs. The comparator is invoked
8371      * with two arguments: (arrVal, othVal).
8372      *
8373      * @static
8374      * @memberOf _
8375      * @since 4.0.0
8376      * @category Array
8377      * @param {...Array} [arrays] The arrays to inspect.
8378      * @param {Function} [comparator] The comparator invoked per element.
8379      * @returns {Array} Returns the new array of combined values.
8380      * @example
8381      *
8382      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8383      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8384      *
8385      * _.unionWith(objects, others, _.isEqual);
8386      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8387      */
8388     var unionWith = baseRest(function(arrays) {
8389       var comparator = last(arrays);
8390       comparator = typeof comparator == 'function' ? comparator : undefined;
8391       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
8392     });
8393
8394     /**
8395      * Creates a duplicate-free version of an array, using
8396      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8397      * for equality comparisons, in which only the first occurrence of each element
8398      * is kept. The order of result values is determined by the order they occur
8399      * in the array.
8400      *
8401      * @static
8402      * @memberOf _
8403      * @since 0.1.0
8404      * @category Array
8405      * @param {Array} array The array to inspect.
8406      * @returns {Array} Returns the new duplicate free array.
8407      * @example
8408      *
8409      * _.uniq([2, 1, 2]);
8410      * // => [2, 1]
8411      */
8412     function uniq(array) {
8413       return (array && array.length) ? baseUniq(array) : [];
8414     }
8415
8416     /**
8417      * This method is like `_.uniq` except that it accepts `iteratee` which is
8418      * invoked for each element in `array` to generate the criterion by which
8419      * uniqueness is computed. The order of result values is determined by the
8420      * order they occur in the array. The iteratee is invoked with one argument:
8421      * (value).
8422      *
8423      * @static
8424      * @memberOf _
8425      * @since 4.0.0
8426      * @category Array
8427      * @param {Array} array The array to inspect.
8428      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8429      * @returns {Array} Returns the new duplicate free array.
8430      * @example
8431      *
8432      * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
8433      * // => [2.1, 1.2]
8434      *
8435      * // The `_.property` iteratee shorthand.
8436      * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
8437      * // => [{ 'x': 1 }, { 'x': 2 }]
8438      */
8439     function uniqBy(array, iteratee) {
8440       return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
8441     }
8442
8443     /**
8444      * This method is like `_.uniq` except that it accepts `comparator` which
8445      * is invoked to compare elements of `array`. The order of result values is
8446      * determined by the order they occur in the array.The comparator is invoked
8447      * with two arguments: (arrVal, othVal).
8448      *
8449      * @static
8450      * @memberOf _
8451      * @since 4.0.0
8452      * @category Array
8453      * @param {Array} array The array to inspect.
8454      * @param {Function} [comparator] The comparator invoked per element.
8455      * @returns {Array} Returns the new duplicate free array.
8456      * @example
8457      *
8458      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
8459      *
8460      * _.uniqWith(objects, _.isEqual);
8461      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
8462      */
8463     function uniqWith(array, comparator) {
8464       comparator = typeof comparator == 'function' ? comparator : undefined;
8465       return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
8466     }
8467
8468     /**
8469      * This method is like `_.zip` except that it accepts an array of grouped
8470      * elements and creates an array regrouping the elements to their pre-zip
8471      * configuration.
8472      *
8473      * @static
8474      * @memberOf _
8475      * @since 1.2.0
8476      * @category Array
8477      * @param {Array} array The array of grouped elements to process.
8478      * @returns {Array} Returns the new array of regrouped elements.
8479      * @example
8480      *
8481      * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
8482      * // => [['a', 1, true], ['b', 2, false]]
8483      *
8484      * _.unzip(zipped);
8485      * // => [['a', 'b'], [1, 2], [true, false]]
8486      */
8487     function unzip(array) {
8488       if (!(array && array.length)) {
8489         return [];
8490       }
8491       var length = 0;
8492       array = arrayFilter(array, function(group) {
8493         if (isArrayLikeObject(group)) {
8494           length = nativeMax(group.length, length);
8495           return true;
8496         }
8497       });
8498       return baseTimes(length, function(index) {
8499         return arrayMap(array, baseProperty(index));
8500       });
8501     }
8502
8503     /**
8504      * This method is like `_.unzip` except that it accepts `iteratee` to specify
8505      * how regrouped values should be combined. The iteratee is invoked with the
8506      * elements of each group: (...group).
8507      *
8508      * @static
8509      * @memberOf _
8510      * @since 3.8.0
8511      * @category Array
8512      * @param {Array} array The array of grouped elements to process.
8513      * @param {Function} [iteratee=_.identity] The function to combine
8514      *  regrouped values.
8515      * @returns {Array} Returns the new array of regrouped elements.
8516      * @example
8517      *
8518      * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
8519      * // => [[1, 10, 100], [2, 20, 200]]
8520      *
8521      * _.unzipWith(zipped, _.add);
8522      * // => [3, 30, 300]
8523      */
8524     function unzipWith(array, iteratee) {
8525       if (!(array && array.length)) {
8526         return [];
8527       }
8528       var result = unzip(array);
8529       if (iteratee == null) {
8530         return result;
8531       }
8532       return arrayMap(result, function(group) {
8533         return apply(iteratee, undefined, group);
8534       });
8535     }
8536
8537     /**
8538      * Creates an array excluding all given values using
8539      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8540      * for equality comparisons.
8541      *
8542      * **Note:** Unlike `_.pull`, this method returns a new array.
8543      *
8544      * @static
8545      * @memberOf _
8546      * @since 0.1.0
8547      * @category Array
8548      * @param {Array} array The array to inspect.
8549      * @param {...*} [values] The values to exclude.
8550      * @returns {Array} Returns the new array of filtered values.
8551      * @see _.difference, _.xor
8552      * @example
8553      *
8554      * _.without([2, 1, 2, 3], 1, 2);
8555      * // => [3]
8556      */
8557     var without = baseRest(function(array, values) {
8558       return isArrayLikeObject(array)
8559         ? baseDifference(array, values)
8560         : [];
8561     });
8562
8563     /**
8564      * Creates an array of unique values that is the
8565      * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
8566      * of the given arrays. The order of result values is determined by the order
8567      * they occur in the arrays.
8568      *
8569      * @static
8570      * @memberOf _
8571      * @since 2.4.0
8572      * @category Array
8573      * @param {...Array} [arrays] The arrays to inspect.
8574      * @returns {Array} Returns the new array of filtered values.
8575      * @see _.difference, _.without
8576      * @example
8577      *
8578      * _.xor([2, 1], [2, 3]);
8579      * // => [1, 3]
8580      */
8581     var xor = baseRest(function(arrays) {
8582       return baseXor(arrayFilter(arrays, isArrayLikeObject));
8583     });
8584
8585     /**
8586      * This method is like `_.xor` except that it accepts `iteratee` which is
8587      * invoked for each element of each `arrays` to generate the criterion by
8588      * which by which they're compared. The order of result values is determined
8589      * by the order they occur in the arrays. The iteratee is invoked with one
8590      * argument: (value).
8591      *
8592      * @static
8593      * @memberOf _
8594      * @since 4.0.0
8595      * @category Array
8596      * @param {...Array} [arrays] The arrays to inspect.
8597      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8598      * @returns {Array} Returns the new array of filtered values.
8599      * @example
8600      *
8601      * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
8602      * // => [1.2, 3.4]
8603      *
8604      * // The `_.property` iteratee shorthand.
8605      * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8606      * // => [{ 'x': 2 }]
8607      */
8608     var xorBy = baseRest(function(arrays) {
8609       var iteratee = last(arrays);
8610       if (isArrayLikeObject(iteratee)) {
8611         iteratee = undefined;
8612       }
8613       return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
8614     });
8615
8616     /**
8617      * This method is like `_.xor` except that it accepts `comparator` which is
8618      * invoked to compare elements of `arrays`. The order of result values is
8619      * determined by the order they occur in the arrays. The comparator is invoked
8620      * with two arguments: (arrVal, othVal).
8621      *
8622      * @static
8623      * @memberOf _
8624      * @since 4.0.0
8625      * @category Array
8626      * @param {...Array} [arrays] The arrays to inspect.
8627      * @param {Function} [comparator] The comparator invoked per element.
8628      * @returns {Array} Returns the new array of filtered values.
8629      * @example
8630      *
8631      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8632      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8633      *
8634      * _.xorWith(objects, others, _.isEqual);
8635      * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8636      */
8637     var xorWith = baseRest(function(arrays) {
8638       var comparator = last(arrays);
8639       comparator = typeof comparator == 'function' ? comparator : undefined;
8640       return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
8641     });
8642
8643     /**
8644      * Creates an array of grouped elements, the first of which contains the
8645      * first elements of the given arrays, the second of which contains the
8646      * second elements of the given arrays, and so on.
8647      *
8648      * @static
8649      * @memberOf _
8650      * @since 0.1.0
8651      * @category Array
8652      * @param {...Array} [arrays] The arrays to process.
8653      * @returns {Array} Returns the new array of grouped elements.
8654      * @example
8655      *
8656      * _.zip(['a', 'b'], [1, 2], [true, false]);
8657      * // => [['a', 1, true], ['b', 2, false]]
8658      */
8659     var zip = baseRest(unzip);
8660
8661     /**
8662      * This method is like `_.fromPairs` except that it accepts two arrays,
8663      * one of property identifiers and one of corresponding values.
8664      *
8665      * @static
8666      * @memberOf _
8667      * @since 0.4.0
8668      * @category Array
8669      * @param {Array} [props=[]] The property identifiers.
8670      * @param {Array} [values=[]] The property values.
8671      * @returns {Object} Returns the new object.
8672      * @example
8673      *
8674      * _.zipObject(['a', 'b'], [1, 2]);
8675      * // => { 'a': 1, 'b': 2 }
8676      */
8677     function zipObject(props, values) {
8678       return baseZipObject(props || [], values || [], assignValue);
8679     }
8680
8681     /**
8682      * This method is like `_.zipObject` except that it supports property paths.
8683      *
8684      * @static
8685      * @memberOf _
8686      * @since 4.1.0
8687      * @category Array
8688      * @param {Array} [props=[]] The property identifiers.
8689      * @param {Array} [values=[]] The property values.
8690      * @returns {Object} Returns the new object.
8691      * @example
8692      *
8693      * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
8694      * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
8695      */
8696     function zipObjectDeep(props, values) {
8697       return baseZipObject(props || [], values || [], baseSet);
8698     }
8699
8700     /**
8701      * This method is like `_.zip` except that it accepts `iteratee` to specify
8702      * how grouped values should be combined. The iteratee is invoked with the
8703      * elements of each group: (...group).
8704      *
8705      * @static
8706      * @memberOf _
8707      * @since 3.8.0
8708      * @category Array
8709      * @param {...Array} [arrays] The arrays to process.
8710      * @param {Function} [iteratee=_.identity] The function to combine
8711      *  grouped values.
8712      * @returns {Array} Returns the new array of grouped elements.
8713      * @example
8714      *
8715      * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
8716      *   return a + b + c;
8717      * });
8718      * // => [111, 222]
8719      */
8720     var zipWith = baseRest(function(arrays) {
8721       var length = arrays.length,
8722           iteratee = length > 1 ? arrays[length - 1] : undefined;
8723
8724       iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
8725       return unzipWith(arrays, iteratee);
8726     });
8727
8728     /*------------------------------------------------------------------------*/
8729
8730     /**
8731      * Creates a `lodash` wrapper instance that wraps `value` with explicit method
8732      * chain sequences enabled. The result of such sequences must be unwrapped
8733      * with `_#value`.
8734      *
8735      * @static
8736      * @memberOf _
8737      * @since 1.3.0
8738      * @category Seq
8739      * @param {*} value The value to wrap.
8740      * @returns {Object} Returns the new `lodash` wrapper instance.
8741      * @example
8742      *
8743      * var users = [
8744      *   { 'user': 'barney',  'age': 36 },
8745      *   { 'user': 'fred',    'age': 40 },
8746      *   { 'user': 'pebbles', 'age': 1 }
8747      * ];
8748      *
8749      * var youngest = _
8750      *   .chain(users)
8751      *   .sortBy('age')
8752      *   .map(function(o) {
8753      *     return o.user + ' is ' + o.age;
8754      *   })
8755      *   .head()
8756      *   .value();
8757      * // => 'pebbles is 1'
8758      */
8759     function chain(value) {
8760       var result = lodash(value);
8761       result.__chain__ = true;
8762       return result;
8763     }
8764
8765     /**
8766      * This method invokes `interceptor` and returns `value`. The interceptor
8767      * is invoked with one argument; (value). The purpose of this method is to
8768      * "tap into" a method chain sequence in order to modify intermediate results.
8769      *
8770      * @static
8771      * @memberOf _
8772      * @since 0.1.0
8773      * @category Seq
8774      * @param {*} value The value to provide to `interceptor`.
8775      * @param {Function} interceptor The function to invoke.
8776      * @returns {*} Returns `value`.
8777      * @example
8778      *
8779      * _([1, 2, 3])
8780      *  .tap(function(array) {
8781      *    // Mutate input array.
8782      *    array.pop();
8783      *  })
8784      *  .reverse()
8785      *  .value();
8786      * // => [2, 1]
8787      */
8788     function tap(value, interceptor) {
8789       interceptor(value);
8790       return value;
8791     }
8792
8793     /**
8794      * This method is like `_.tap` except that it returns the result of `interceptor`.
8795      * The purpose of this method is to "pass thru" values replacing intermediate
8796      * results in a method chain sequence.
8797      *
8798      * @static
8799      * @memberOf _
8800      * @since 3.0.0
8801      * @category Seq
8802      * @param {*} value The value to provide to `interceptor`.
8803      * @param {Function} interceptor The function to invoke.
8804      * @returns {*} Returns the result of `interceptor`.
8805      * @example
8806      *
8807      * _('  abc  ')
8808      *  .chain()
8809      *  .trim()
8810      *  .thru(function(value) {
8811      *    return [value];
8812      *  })
8813      *  .value();
8814      * // => ['abc']
8815      */
8816     function thru(value, interceptor) {
8817       return interceptor(value);
8818     }
8819
8820     /**
8821      * This method is the wrapper version of `_.at`.
8822      *
8823      * @name at
8824      * @memberOf _
8825      * @since 1.0.0
8826      * @category Seq
8827      * @param {...(string|string[])} [paths] The property paths to pick.
8828      * @returns {Object} Returns the new `lodash` wrapper instance.
8829      * @example
8830      *
8831      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
8832      *
8833      * _(object).at(['a[0].b.c', 'a[1]']).value();
8834      * // => [3, 4]
8835      */
8836     var wrapperAt = flatRest(function(paths) {
8837       var length = paths.length,
8838           start = length ? paths[0] : 0,
8839           value = this.__wrapped__,
8840           interceptor = function(object) { return baseAt(object, paths); };
8841
8842       if (length > 1 || this.__actions__.length ||
8843           !(value instanceof LazyWrapper) || !isIndex(start)) {
8844         return this.thru(interceptor);
8845       }
8846       value = value.slice(start, +start + (length ? 1 : 0));
8847       value.__actions__.push({
8848         'func': thru,
8849         'args': [interceptor],
8850         'thisArg': undefined
8851       });
8852       return new LodashWrapper(value, this.__chain__).thru(function(array) {
8853         if (length && !array.length) {
8854           array.push(undefined);
8855         }
8856         return array;
8857       });
8858     });
8859
8860     /**
8861      * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
8862      *
8863      * @name chain
8864      * @memberOf _
8865      * @since 0.1.0
8866      * @category Seq
8867      * @returns {Object} Returns the new `lodash` wrapper instance.
8868      * @example
8869      *
8870      * var users = [
8871      *   { 'user': 'barney', 'age': 36 },
8872      *   { 'user': 'fred',   'age': 40 }
8873      * ];
8874      *
8875      * // A sequence without explicit chaining.
8876      * _(users).head();
8877      * // => { 'user': 'barney', 'age': 36 }
8878      *
8879      * // A sequence with explicit chaining.
8880      * _(users)
8881      *   .chain()
8882      *   .head()
8883      *   .pick('user')
8884      *   .value();
8885      * // => { 'user': 'barney' }
8886      */
8887     function wrapperChain() {
8888       return chain(this);
8889     }
8890
8891     /**
8892      * Executes the chain sequence and returns the wrapped result.
8893      *
8894      * @name commit
8895      * @memberOf _
8896      * @since 3.2.0
8897      * @category Seq
8898      * @returns {Object} Returns the new `lodash` wrapper instance.
8899      * @example
8900      *
8901      * var array = [1, 2];
8902      * var wrapped = _(array).push(3);
8903      *
8904      * console.log(array);
8905      * // => [1, 2]
8906      *
8907      * wrapped = wrapped.commit();
8908      * console.log(array);
8909      * // => [1, 2, 3]
8910      *
8911      * wrapped.last();
8912      * // => 3
8913      *
8914      * console.log(array);
8915      * // => [1, 2, 3]
8916      */
8917     function wrapperCommit() {
8918       return new LodashWrapper(this.value(), this.__chain__);
8919     }
8920
8921     /**
8922      * Gets the next value on a wrapped object following the
8923      * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
8924      *
8925      * @name next
8926      * @memberOf _
8927      * @since 4.0.0
8928      * @category Seq
8929      * @returns {Object} Returns the next iterator value.
8930      * @example
8931      *
8932      * var wrapped = _([1, 2]);
8933      *
8934      * wrapped.next();
8935      * // => { 'done': false, 'value': 1 }
8936      *
8937      * wrapped.next();
8938      * // => { 'done': false, 'value': 2 }
8939      *
8940      * wrapped.next();
8941      * // => { 'done': true, 'value': undefined }
8942      */
8943     function wrapperNext() {
8944       if (this.__values__ === undefined) {
8945         this.__values__ = toArray(this.value());
8946       }
8947       var done = this.__index__ >= this.__values__.length,
8948           value = done ? undefined : this.__values__[this.__index__++];
8949
8950       return { 'done': done, 'value': value };
8951     }
8952
8953     /**
8954      * Enables the wrapper to be iterable.
8955      *
8956      * @name Symbol.iterator
8957      * @memberOf _
8958      * @since 4.0.0
8959      * @category Seq
8960      * @returns {Object} Returns the wrapper object.
8961      * @example
8962      *
8963      * var wrapped = _([1, 2]);
8964      *
8965      * wrapped[Symbol.iterator]() === wrapped;
8966      * // => true
8967      *
8968      * Array.from(wrapped);
8969      * // => [1, 2]
8970      */
8971     function wrapperToIterator() {
8972       return this;
8973     }
8974
8975     /**
8976      * Creates a clone of the chain sequence planting `value` as the wrapped value.
8977      *
8978      * @name plant
8979      * @memberOf _
8980      * @since 3.2.0
8981      * @category Seq
8982      * @param {*} value The value to plant.
8983      * @returns {Object} Returns the new `lodash` wrapper instance.
8984      * @example
8985      *
8986      * function square(n) {
8987      *   return n * n;
8988      * }
8989      *
8990      * var wrapped = _([1, 2]).map(square);
8991      * var other = wrapped.plant([3, 4]);
8992      *
8993      * other.value();
8994      * // => [9, 16]
8995      *
8996      * wrapped.value();
8997      * // => [1, 4]
8998      */
8999     function wrapperPlant(value) {
9000       var result,
9001           parent = this;
9002
9003       while (parent instanceof baseLodash) {
9004         var clone = wrapperClone(parent);
9005         clone.__index__ = 0;
9006         clone.__values__ = undefined;
9007         if (result) {
9008           previous.__wrapped__ = clone;
9009         } else {
9010           result = clone;
9011         }
9012         var previous = clone;
9013         parent = parent.__wrapped__;
9014       }
9015       previous.__wrapped__ = value;
9016       return result;
9017     }
9018
9019     /**
9020      * This method is the wrapper version of `_.reverse`.
9021      *
9022      * **Note:** This method mutates the wrapped array.
9023      *
9024      * @name reverse
9025      * @memberOf _
9026      * @since 0.1.0
9027      * @category Seq
9028      * @returns {Object} Returns the new `lodash` wrapper instance.
9029      * @example
9030      *
9031      * var array = [1, 2, 3];
9032      *
9033      * _(array).reverse().value()
9034      * // => [3, 2, 1]
9035      *
9036      * console.log(array);
9037      * // => [3, 2, 1]
9038      */
9039     function wrapperReverse() {
9040       var value = this.__wrapped__;
9041       if (value instanceof LazyWrapper) {
9042         var wrapped = value;
9043         if (this.__actions__.length) {
9044           wrapped = new LazyWrapper(this);
9045         }
9046         wrapped = wrapped.reverse();
9047         wrapped.__actions__.push({
9048           'func': thru,
9049           'args': [reverse],
9050           'thisArg': undefined
9051         });
9052         return new LodashWrapper(wrapped, this.__chain__);
9053       }
9054       return this.thru(reverse);
9055     }
9056
9057     /**
9058      * Executes the chain sequence to resolve the unwrapped value.
9059      *
9060      * @name value
9061      * @memberOf _
9062      * @since 0.1.0
9063      * @alias toJSON, valueOf
9064      * @category Seq
9065      * @returns {*} Returns the resolved unwrapped value.
9066      * @example
9067      *
9068      * _([1, 2, 3]).value();
9069      * // => [1, 2, 3]
9070      */
9071     function wrapperValue() {
9072       return baseWrapperValue(this.__wrapped__, this.__actions__);
9073     }
9074
9075     /*------------------------------------------------------------------------*/
9076
9077     /**
9078      * Creates an object composed of keys generated from the results of running
9079      * each element of `collection` thru `iteratee`. The corresponding value of
9080      * each key is the number of times the key was returned by `iteratee`. The
9081      * iteratee is invoked with one argument: (value).
9082      *
9083      * @static
9084      * @memberOf _
9085      * @since 0.5.0
9086      * @category Collection
9087      * @param {Array|Object} collection The collection to iterate over.
9088      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9089      * @returns {Object} Returns the composed aggregate object.
9090      * @example
9091      *
9092      * _.countBy([6.1, 4.2, 6.3], Math.floor);
9093      * // => { '4': 1, '6': 2 }
9094      *
9095      * // The `_.property` iteratee shorthand.
9096      * _.countBy(['one', 'two', 'three'], 'length');
9097      * // => { '3': 2, '5': 1 }
9098      */
9099     var countBy = createAggregator(function(result, value, key) {
9100       if (hasOwnProperty.call(result, key)) {
9101         ++result[key];
9102       } else {
9103         baseAssignValue(result, key, 1);
9104       }
9105     });
9106
9107     /**
9108      * Checks if `predicate` returns truthy for **all** elements of `collection`.
9109      * Iteration is stopped once `predicate` returns falsey. The predicate is
9110      * invoked with three arguments: (value, index|key, collection).
9111      *
9112      * **Note:** This method returns `true` for
9113      * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
9114      * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
9115      * elements of empty collections.
9116      *
9117      * @static
9118      * @memberOf _
9119      * @since 0.1.0
9120      * @category Collection
9121      * @param {Array|Object} collection The collection to iterate over.
9122      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9123      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9124      * @returns {boolean} Returns `true` if all elements pass the predicate check,
9125      *  else `false`.
9126      * @example
9127      *
9128      * _.every([true, 1, null, 'yes'], Boolean);
9129      * // => false
9130      *
9131      * var users = [
9132      *   { 'user': 'barney', 'age': 36, 'active': false },
9133      *   { 'user': 'fred',   'age': 40, 'active': false }
9134      * ];
9135      *
9136      * // The `_.matches` iteratee shorthand.
9137      * _.every(users, { 'user': 'barney', 'active': false });
9138      * // => false
9139      *
9140      * // The `_.matchesProperty` iteratee shorthand.
9141      * _.every(users, ['active', false]);
9142      * // => true
9143      *
9144      * // The `_.property` iteratee shorthand.
9145      * _.every(users, 'active');
9146      * // => false
9147      */
9148     function every(collection, predicate, guard) {
9149       var func = isArray(collection) ? arrayEvery : baseEvery;
9150       if (guard && isIterateeCall(collection, predicate, guard)) {
9151         predicate = undefined;
9152       }
9153       return func(collection, getIteratee(predicate, 3));
9154     }
9155
9156     /**
9157      * Iterates over elements of `collection`, returning an array of all elements
9158      * `predicate` returns truthy for. The predicate is invoked with three
9159      * arguments: (value, index|key, collection).
9160      *
9161      * **Note:** Unlike `_.remove`, this method returns a new array.
9162      *
9163      * @static
9164      * @memberOf _
9165      * @since 0.1.0
9166      * @category Collection
9167      * @param {Array|Object} collection The collection to iterate over.
9168      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9169      * @returns {Array} Returns the new filtered array.
9170      * @see _.reject
9171      * @example
9172      *
9173      * var users = [
9174      *   { 'user': 'barney', 'age': 36, 'active': true },
9175      *   { 'user': 'fred',   'age': 40, 'active': false }
9176      * ];
9177      *
9178      * _.filter(users, function(o) { return !o.active; });
9179      * // => objects for ['fred']
9180      *
9181      * // The `_.matches` iteratee shorthand.
9182      * _.filter(users, { 'age': 36, 'active': true });
9183      * // => objects for ['barney']
9184      *
9185      * // The `_.matchesProperty` iteratee shorthand.
9186      * _.filter(users, ['active', false]);
9187      * // => objects for ['fred']
9188      *
9189      * // The `_.property` iteratee shorthand.
9190      * _.filter(users, 'active');
9191      * // => objects for ['barney']
9192      */
9193     function filter(collection, predicate) {
9194       var func = isArray(collection) ? arrayFilter : baseFilter;
9195       return func(collection, getIteratee(predicate, 3));
9196     }
9197
9198     /**
9199      * Iterates over elements of `collection`, returning the first element
9200      * `predicate` returns truthy for. The predicate is invoked with three
9201      * arguments: (value, index|key, collection).
9202      *
9203      * @static
9204      * @memberOf _
9205      * @since 0.1.0
9206      * @category Collection
9207      * @param {Array|Object} collection The collection to inspect.
9208      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9209      * @param {number} [fromIndex=0] The index to search from.
9210      * @returns {*} Returns the matched element, else `undefined`.
9211      * @example
9212      *
9213      * var users = [
9214      *   { 'user': 'barney',  'age': 36, 'active': true },
9215      *   { 'user': 'fred',    'age': 40, 'active': false },
9216      *   { 'user': 'pebbles', 'age': 1,  'active': true }
9217      * ];
9218      *
9219      * _.find(users, function(o) { return o.age < 40; });
9220      * // => object for 'barney'
9221      *
9222      * // The `_.matches` iteratee shorthand.
9223      * _.find(users, { 'age': 1, 'active': true });
9224      * // => object for 'pebbles'
9225      *
9226      * // The `_.matchesProperty` iteratee shorthand.
9227      * _.find(users, ['active', false]);
9228      * // => object for 'fred'
9229      *
9230      * // The `_.property` iteratee shorthand.
9231      * _.find(users, 'active');
9232      * // => object for 'barney'
9233      */
9234     var find = createFind(findIndex);
9235
9236     /**
9237      * This method is like `_.find` except that it iterates over elements of
9238      * `collection` from right to left.
9239      *
9240      * @static
9241      * @memberOf _
9242      * @since 2.0.0
9243      * @category Collection
9244      * @param {Array|Object} collection The collection to inspect.
9245      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9246      * @param {number} [fromIndex=collection.length-1] The index to search from.
9247      * @returns {*} Returns the matched element, else `undefined`.
9248      * @example
9249      *
9250      * _.findLast([1, 2, 3, 4], function(n) {
9251      *   return n % 2 == 1;
9252      * });
9253      * // => 3
9254      */
9255     var findLast = createFind(findLastIndex);
9256
9257     /**
9258      * Creates a flattened array of values by running each element in `collection`
9259      * thru `iteratee` and flattening the mapped results. The iteratee is invoked
9260      * with three arguments: (value, index|key, collection).
9261      *
9262      * @static
9263      * @memberOf _
9264      * @since 4.0.0
9265      * @category Collection
9266      * @param {Array|Object} collection The collection to iterate over.
9267      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9268      * @returns {Array} Returns the new flattened array.
9269      * @example
9270      *
9271      * function duplicate(n) {
9272      *   return [n, n];
9273      * }
9274      *
9275      * _.flatMap([1, 2], duplicate);
9276      * // => [1, 1, 2, 2]
9277      */
9278     function flatMap(collection, iteratee) {
9279       return baseFlatten(map(collection, iteratee), 1);
9280     }
9281
9282     /**
9283      * This method is like `_.flatMap` except that it recursively flattens the
9284      * mapped results.
9285      *
9286      * @static
9287      * @memberOf _
9288      * @since 4.7.0
9289      * @category Collection
9290      * @param {Array|Object} collection The collection to iterate over.
9291      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9292      * @returns {Array} Returns the new flattened array.
9293      * @example
9294      *
9295      * function duplicate(n) {
9296      *   return [[[n, n]]];
9297      * }
9298      *
9299      * _.flatMapDeep([1, 2], duplicate);
9300      * // => [1, 1, 2, 2]
9301      */
9302     function flatMapDeep(collection, iteratee) {
9303       return baseFlatten(map(collection, iteratee), INFINITY);
9304     }
9305
9306     /**
9307      * This method is like `_.flatMap` except that it recursively flattens the
9308      * mapped results up to `depth` times.
9309      *
9310      * @static
9311      * @memberOf _
9312      * @since 4.7.0
9313      * @category Collection
9314      * @param {Array|Object} collection The collection to iterate over.
9315      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9316      * @param {number} [depth=1] The maximum recursion depth.
9317      * @returns {Array} Returns the new flattened array.
9318      * @example
9319      *
9320      * function duplicate(n) {
9321      *   return [[[n, n]]];
9322      * }
9323      *
9324      * _.flatMapDepth([1, 2], duplicate, 2);
9325      * // => [[1, 1], [2, 2]]
9326      */
9327     function flatMapDepth(collection, iteratee, depth) {
9328       depth = depth === undefined ? 1 : toInteger(depth);
9329       return baseFlatten(map(collection, iteratee), depth);
9330     }
9331
9332     /**
9333      * Iterates over elements of `collection` and invokes `iteratee` for each element.
9334      * The iteratee is invoked with three arguments: (value, index|key, collection).
9335      * Iteratee functions may exit iteration early by explicitly returning `false`.
9336      *
9337      * **Note:** As with other "Collections" methods, objects with a "length"
9338      * property are iterated like arrays. To avoid this behavior use `_.forIn`
9339      * or `_.forOwn` for object iteration.
9340      *
9341      * @static
9342      * @memberOf _
9343      * @since 0.1.0
9344      * @alias each
9345      * @category Collection
9346      * @param {Array|Object} collection The collection to iterate over.
9347      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9348      * @returns {Array|Object} Returns `collection`.
9349      * @see _.forEachRight
9350      * @example
9351      *
9352      * _.forEach([1, 2], function(value) {
9353      *   console.log(value);
9354      * });
9355      * // => Logs `1` then `2`.
9356      *
9357      * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
9358      *   console.log(key);
9359      * });
9360      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
9361      */
9362     function forEach(collection, iteratee) {
9363       var func = isArray(collection) ? arrayEach : baseEach;
9364       return func(collection, getIteratee(iteratee, 3));
9365     }
9366
9367     /**
9368      * This method is like `_.forEach` except that it iterates over elements of
9369      * `collection` from right to left.
9370      *
9371      * @static
9372      * @memberOf _
9373      * @since 2.0.0
9374      * @alias eachRight
9375      * @category Collection
9376      * @param {Array|Object} collection The collection to iterate over.
9377      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9378      * @returns {Array|Object} Returns `collection`.
9379      * @see _.forEach
9380      * @example
9381      *
9382      * _.forEachRight([1, 2], function(value) {
9383      *   console.log(value);
9384      * });
9385      * // => Logs `2` then `1`.
9386      */
9387     function forEachRight(collection, iteratee) {
9388       var func = isArray(collection) ? arrayEachRight : baseEachRight;
9389       return func(collection, getIteratee(iteratee, 3));
9390     }
9391
9392     /**
9393      * Creates an object composed of keys generated from the results of running
9394      * each element of `collection` thru `iteratee`. The order of grouped values
9395      * is determined by the order they occur in `collection`. The corresponding
9396      * value of each key is an array of elements responsible for generating the
9397      * key. The iteratee is invoked with one argument: (value).
9398      *
9399      * @static
9400      * @memberOf _
9401      * @since 0.1.0
9402      * @category Collection
9403      * @param {Array|Object} collection The collection to iterate over.
9404      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9405      * @returns {Object} Returns the composed aggregate object.
9406      * @example
9407      *
9408      * _.groupBy([6.1, 4.2, 6.3], Math.floor);
9409      * // => { '4': [4.2], '6': [6.1, 6.3] }
9410      *
9411      * // The `_.property` iteratee shorthand.
9412      * _.groupBy(['one', 'two', 'three'], 'length');
9413      * // => { '3': ['one', 'two'], '5': ['three'] }
9414      */
9415     var groupBy = createAggregator(function(result, value, key) {
9416       if (hasOwnProperty.call(result, key)) {
9417         result[key].push(value);
9418       } else {
9419         baseAssignValue(result, key, [value]);
9420       }
9421     });
9422
9423     /**
9424      * Checks if `value` is in `collection`. If `collection` is a string, it's
9425      * checked for a substring of `value`, otherwise
9426      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
9427      * is used for equality comparisons. If `fromIndex` is negative, it's used as
9428      * the offset from the end of `collection`.
9429      *
9430      * @static
9431      * @memberOf _
9432      * @since 0.1.0
9433      * @category Collection
9434      * @param {Array|Object|string} collection The collection to inspect.
9435      * @param {*} value The value to search for.
9436      * @param {number} [fromIndex=0] The index to search from.
9437      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9438      * @returns {boolean} Returns `true` if `value` is found, else `false`.
9439      * @example
9440      *
9441      * _.includes([1, 2, 3], 1);
9442      * // => true
9443      *
9444      * _.includes([1, 2, 3], 1, 2);
9445      * // => false
9446      *
9447      * _.includes({ 'a': 1, 'b': 2 }, 1);
9448      * // => true
9449      *
9450      * _.includes('abcd', 'bc');
9451      * // => true
9452      */
9453     function includes(collection, value, fromIndex, guard) {
9454       collection = isArrayLike(collection) ? collection : values(collection);
9455       fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
9456
9457       var length = collection.length;
9458       if (fromIndex < 0) {
9459         fromIndex = nativeMax(length + fromIndex, 0);
9460       }
9461       return isString(collection)
9462         ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
9463         : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
9464     }
9465
9466     /**
9467      * Invokes the method at `path` of each element in `collection`, returning
9468      * an array of the results of each invoked method. Any additional arguments
9469      * are provided to each invoked method. If `path` is a function, it's invoked
9470      * for, and `this` bound to, each element in `collection`.
9471      *
9472      * @static
9473      * @memberOf _
9474      * @since 4.0.0
9475      * @category Collection
9476      * @param {Array|Object} collection The collection to iterate over.
9477      * @param {Array|Function|string} path The path of the method to invoke or
9478      *  the function invoked per iteration.
9479      * @param {...*} [args] The arguments to invoke each method with.
9480      * @returns {Array} Returns the array of results.
9481      * @example
9482      *
9483      * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
9484      * // => [[1, 5, 7], [1, 2, 3]]
9485      *
9486      * _.invokeMap([123, 456], String.prototype.split, '');
9487      * // => [['1', '2', '3'], ['4', '5', '6']]
9488      */
9489     var invokeMap = baseRest(function(collection, path, args) {
9490       var index = -1,
9491           isFunc = typeof path == 'function',
9492           result = isArrayLike(collection) ? Array(collection.length) : [];
9493
9494       baseEach(collection, function(value) {
9495         result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
9496       });
9497       return result;
9498     });
9499
9500     /**
9501      * Creates an object composed of keys generated from the results of running
9502      * each element of `collection` thru `iteratee`. The corresponding value of
9503      * each key is the last element responsible for generating the key. The
9504      * iteratee is invoked with one argument: (value).
9505      *
9506      * @static
9507      * @memberOf _
9508      * @since 4.0.0
9509      * @category Collection
9510      * @param {Array|Object} collection The collection to iterate over.
9511      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9512      * @returns {Object} Returns the composed aggregate object.
9513      * @example
9514      *
9515      * var array = [
9516      *   { 'dir': 'left', 'code': 97 },
9517      *   { 'dir': 'right', 'code': 100 }
9518      * ];
9519      *
9520      * _.keyBy(array, function(o) {
9521      *   return String.fromCharCode(o.code);
9522      * });
9523      * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
9524      *
9525      * _.keyBy(array, 'dir');
9526      * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
9527      */
9528     var keyBy = createAggregator(function(result, value, key) {
9529       baseAssignValue(result, key, value);
9530     });
9531
9532     /**
9533      * Creates an array of values by running each element in `collection` thru
9534      * `iteratee`. The iteratee is invoked with three arguments:
9535      * (value, index|key, collection).
9536      *
9537      * Many lodash methods are guarded to work as iteratees for methods like
9538      * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
9539      *
9540      * The guarded methods are:
9541      * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
9542      * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
9543      * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
9544      * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
9545      *
9546      * @static
9547      * @memberOf _
9548      * @since 0.1.0
9549      * @category Collection
9550      * @param {Array|Object} collection The collection to iterate over.
9551      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9552      * @returns {Array} Returns the new mapped array.
9553      * @example
9554      *
9555      * function square(n) {
9556      *   return n * n;
9557      * }
9558      *
9559      * _.map([4, 8], square);
9560      * // => [16, 64]
9561      *
9562      * _.map({ 'a': 4, 'b': 8 }, square);
9563      * // => [16, 64] (iteration order is not guaranteed)
9564      *
9565      * var users = [
9566      *   { 'user': 'barney' },
9567      *   { 'user': 'fred' }
9568      * ];
9569      *
9570      * // The `_.property` iteratee shorthand.
9571      * _.map(users, 'user');
9572      * // => ['barney', 'fred']
9573      */
9574     function map(collection, iteratee) {
9575       var func = isArray(collection) ? arrayMap : baseMap;
9576       return func(collection, getIteratee(iteratee, 3));
9577     }
9578
9579     /**
9580      * This method is like `_.sortBy` except that it allows specifying the sort
9581      * orders of the iteratees to sort by. If `orders` is unspecified, all values
9582      * are sorted in ascending order. Otherwise, specify an order of "desc" for
9583      * descending or "asc" for ascending sort order of corresponding values.
9584      *
9585      * @static
9586      * @memberOf _
9587      * @since 4.0.0
9588      * @category Collection
9589      * @param {Array|Object} collection The collection to iterate over.
9590      * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
9591      *  The iteratees to sort by.
9592      * @param {string[]} [orders] The sort orders of `iteratees`.
9593      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9594      * @returns {Array} Returns the new sorted array.
9595      * @example
9596      *
9597      * var users = [
9598      *   { 'user': 'fred',   'age': 48 },
9599      *   { 'user': 'barney', 'age': 34 },
9600      *   { 'user': 'fred',   'age': 40 },
9601      *   { 'user': 'barney', 'age': 36 }
9602      * ];
9603      *
9604      * // Sort by `user` in ascending order and by `age` in descending order.
9605      * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
9606      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9607      */
9608     function orderBy(collection, iteratees, orders, guard) {
9609       if (collection == null) {
9610         return [];
9611       }
9612       if (!isArray(iteratees)) {
9613         iteratees = iteratees == null ? [] : [iteratees];
9614       }
9615       orders = guard ? undefined : orders;
9616       if (!isArray(orders)) {
9617         orders = orders == null ? [] : [orders];
9618       }
9619       return baseOrderBy(collection, iteratees, orders);
9620     }
9621
9622     /**
9623      * Creates an array of elements split into two groups, the first of which
9624      * contains elements `predicate` returns truthy for, the second of which
9625      * contains elements `predicate` returns falsey for. The predicate is
9626      * invoked with one argument: (value).
9627      *
9628      * @static
9629      * @memberOf _
9630      * @since 3.0.0
9631      * @category Collection
9632      * @param {Array|Object} collection The collection to iterate over.
9633      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9634      * @returns {Array} Returns the array of grouped elements.
9635      * @example
9636      *
9637      * var users = [
9638      *   { 'user': 'barney',  'age': 36, 'active': false },
9639      *   { 'user': 'fred',    'age': 40, 'active': true },
9640      *   { 'user': 'pebbles', 'age': 1,  'active': false }
9641      * ];
9642      *
9643      * _.partition(users, function(o) { return o.active; });
9644      * // => objects for [['fred'], ['barney', 'pebbles']]
9645      *
9646      * // The `_.matches` iteratee shorthand.
9647      * _.partition(users, { 'age': 1, 'active': false });
9648      * // => objects for [['pebbles'], ['barney', 'fred']]
9649      *
9650      * // The `_.matchesProperty` iteratee shorthand.
9651      * _.partition(users, ['active', false]);
9652      * // => objects for [['barney', 'pebbles'], ['fred']]
9653      *
9654      * // The `_.property` iteratee shorthand.
9655      * _.partition(users, 'active');
9656      * // => objects for [['fred'], ['barney', 'pebbles']]
9657      */
9658     var partition = createAggregator(function(result, value, key) {
9659       result[key ? 0 : 1].push(value);
9660     }, function() { return [[], []]; });
9661
9662     /**
9663      * Reduces `collection` to a value which is the accumulated result of running
9664      * each element in `collection` thru `iteratee`, where each successive
9665      * invocation is supplied the return value of the previous. If `accumulator`
9666      * is not given, the first element of `collection` is used as the initial
9667      * value. The iteratee is invoked with four arguments:
9668      * (accumulator, value, index|key, collection).
9669      *
9670      * Many lodash methods are guarded to work as iteratees for methods like
9671      * `_.reduce`, `_.reduceRight`, and `_.transform`.
9672      *
9673      * The guarded methods are:
9674      * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
9675      * and `sortBy`
9676      *
9677      * @static
9678      * @memberOf _
9679      * @since 0.1.0
9680      * @category Collection
9681      * @param {Array|Object} collection The collection to iterate over.
9682      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9683      * @param {*} [accumulator] The initial value.
9684      * @returns {*} Returns the accumulated value.
9685      * @see _.reduceRight
9686      * @example
9687      *
9688      * _.reduce([1, 2], function(sum, n) {
9689      *   return sum + n;
9690      * }, 0);
9691      * // => 3
9692      *
9693      * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
9694      *   (result[value] || (result[value] = [])).push(key);
9695      *   return result;
9696      * }, {});
9697      * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
9698      */
9699     function reduce(collection, iteratee, accumulator) {
9700       var func = isArray(collection) ? arrayReduce : baseReduce,
9701           initAccum = arguments.length < 3;
9702
9703       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
9704     }
9705
9706     /**
9707      * This method is like `_.reduce` except that it iterates over elements of
9708      * `collection` from right to left.
9709      *
9710      * @static
9711      * @memberOf _
9712      * @since 0.1.0
9713      * @category Collection
9714      * @param {Array|Object} collection The collection to iterate over.
9715      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9716      * @param {*} [accumulator] The initial value.
9717      * @returns {*} Returns the accumulated value.
9718      * @see _.reduce
9719      * @example
9720      *
9721      * var array = [[0, 1], [2, 3], [4, 5]];
9722      *
9723      * _.reduceRight(array, function(flattened, other) {
9724      *   return flattened.concat(other);
9725      * }, []);
9726      * // => [4, 5, 2, 3, 0, 1]
9727      */
9728     function reduceRight(collection, iteratee, accumulator) {
9729       var func = isArray(collection) ? arrayReduceRight : baseReduce,
9730           initAccum = arguments.length < 3;
9731
9732       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
9733     }
9734
9735     /**
9736      * The opposite of `_.filter`; this method returns the elements of `collection`
9737      * that `predicate` does **not** return truthy for.
9738      *
9739      * @static
9740      * @memberOf _
9741      * @since 0.1.0
9742      * @category Collection
9743      * @param {Array|Object} collection The collection to iterate over.
9744      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9745      * @returns {Array} Returns the new filtered array.
9746      * @see _.filter
9747      * @example
9748      *
9749      * var users = [
9750      *   { 'user': 'barney', 'age': 36, 'active': false },
9751      *   { 'user': 'fred',   'age': 40, 'active': true }
9752      * ];
9753      *
9754      * _.reject(users, function(o) { return !o.active; });
9755      * // => objects for ['fred']
9756      *
9757      * // The `_.matches` iteratee shorthand.
9758      * _.reject(users, { 'age': 40, 'active': true });
9759      * // => objects for ['barney']
9760      *
9761      * // The `_.matchesProperty` iteratee shorthand.
9762      * _.reject(users, ['active', false]);
9763      * // => objects for ['fred']
9764      *
9765      * // The `_.property` iteratee shorthand.
9766      * _.reject(users, 'active');
9767      * // => objects for ['barney']
9768      */
9769     function reject(collection, predicate) {
9770       var func = isArray(collection) ? arrayFilter : baseFilter;
9771       return func(collection, negate(getIteratee(predicate, 3)));
9772     }
9773
9774     /**
9775      * Gets a random element from `collection`.
9776      *
9777      * @static
9778      * @memberOf _
9779      * @since 2.0.0
9780      * @category Collection
9781      * @param {Array|Object} collection The collection to sample.
9782      * @returns {*} Returns the random element.
9783      * @example
9784      *
9785      * _.sample([1, 2, 3, 4]);
9786      * // => 2
9787      */
9788     function sample(collection) {
9789       var func = isArray(collection) ? arraySample : baseSample;
9790       return func(collection);
9791     }
9792
9793     /**
9794      * Gets `n` random elements at unique keys from `collection` up to the
9795      * size of `collection`.
9796      *
9797      * @static
9798      * @memberOf _
9799      * @since 4.0.0
9800      * @category Collection
9801      * @param {Array|Object} collection The collection to sample.
9802      * @param {number} [n=1] The number of elements to sample.
9803      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9804      * @returns {Array} Returns the random elements.
9805      * @example
9806      *
9807      * _.sampleSize([1, 2, 3], 2);
9808      * // => [3, 1]
9809      *
9810      * _.sampleSize([1, 2, 3], 4);
9811      * // => [2, 3, 1]
9812      */
9813     function sampleSize(collection, n, guard) {
9814       if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
9815         n = 1;
9816       } else {
9817         n = toInteger(n);
9818       }
9819       var func = isArray(collection) ? arraySampleSize : baseSampleSize;
9820       return func(collection, n);
9821     }
9822
9823     /**
9824      * Creates an array of shuffled values, using a version of the
9825      * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
9826      *
9827      * @static
9828      * @memberOf _
9829      * @since 0.1.0
9830      * @category Collection
9831      * @param {Array|Object} collection The collection to shuffle.
9832      * @returns {Array} Returns the new shuffled array.
9833      * @example
9834      *
9835      * _.shuffle([1, 2, 3, 4]);
9836      * // => [4, 1, 3, 2]
9837      */
9838     function shuffle(collection) {
9839       var func = isArray(collection) ? arrayShuffle : baseShuffle;
9840       return func(collection);
9841     }
9842
9843     /**
9844      * Gets the size of `collection` by returning its length for array-like
9845      * values or the number of own enumerable string keyed properties for objects.
9846      *
9847      * @static
9848      * @memberOf _
9849      * @since 0.1.0
9850      * @category Collection
9851      * @param {Array|Object|string} collection The collection to inspect.
9852      * @returns {number} Returns the collection size.
9853      * @example
9854      *
9855      * _.size([1, 2, 3]);
9856      * // => 3
9857      *
9858      * _.size({ 'a': 1, 'b': 2 });
9859      * // => 2
9860      *
9861      * _.size('pebbles');
9862      * // => 7
9863      */
9864     function size(collection) {
9865       if (collection == null) {
9866         return 0;
9867       }
9868       if (isArrayLike(collection)) {
9869         return isString(collection) ? stringSize(collection) : collection.length;
9870       }
9871       var tag = getTag(collection);
9872       if (tag == mapTag || tag == setTag) {
9873         return collection.size;
9874       }
9875       return baseKeys(collection).length;
9876     }
9877
9878     /**
9879      * Checks if `predicate` returns truthy for **any** element of `collection`.
9880      * Iteration is stopped once `predicate` returns truthy. The predicate is
9881      * invoked with three arguments: (value, index|key, collection).
9882      *
9883      * @static
9884      * @memberOf _
9885      * @since 0.1.0
9886      * @category Collection
9887      * @param {Array|Object} collection The collection to iterate over.
9888      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9889      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9890      * @returns {boolean} Returns `true` if any element passes the predicate check,
9891      *  else `false`.
9892      * @example
9893      *
9894      * _.some([null, 0, 'yes', false], Boolean);
9895      * // => true
9896      *
9897      * var users = [
9898      *   { 'user': 'barney', 'active': true },
9899      *   { 'user': 'fred',   'active': false }
9900      * ];
9901      *
9902      * // The `_.matches` iteratee shorthand.
9903      * _.some(users, { 'user': 'barney', 'active': false });
9904      * // => false
9905      *
9906      * // The `_.matchesProperty` iteratee shorthand.
9907      * _.some(users, ['active', false]);
9908      * // => true
9909      *
9910      * // The `_.property` iteratee shorthand.
9911      * _.some(users, 'active');
9912      * // => true
9913      */
9914     function some(collection, predicate, guard) {
9915       var func = isArray(collection) ? arraySome : baseSome;
9916       if (guard && isIterateeCall(collection, predicate, guard)) {
9917         predicate = undefined;
9918       }
9919       return func(collection, getIteratee(predicate, 3));
9920     }
9921
9922     /**
9923      * Creates an array of elements, sorted in ascending order by the results of
9924      * running each element in a collection thru each iteratee. This method
9925      * performs a stable sort, that is, it preserves the original sort order of
9926      * equal elements. The iteratees are invoked with one argument: (value).
9927      *
9928      * @static
9929      * @memberOf _
9930      * @since 0.1.0
9931      * @category Collection
9932      * @param {Array|Object} collection The collection to iterate over.
9933      * @param {...(Function|Function[])} [iteratees=[_.identity]]
9934      *  The iteratees to sort by.
9935      * @returns {Array} Returns the new sorted array.
9936      * @example
9937      *
9938      * var users = [
9939      *   { 'user': 'fred',   'age': 48 },
9940      *   { 'user': 'barney', 'age': 36 },
9941      *   { 'user': 'fred',   'age': 40 },
9942      *   { 'user': 'barney', 'age': 34 }
9943      * ];
9944      *
9945      * _.sortBy(users, [function(o) { return o.user; }]);
9946      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9947      *
9948      * _.sortBy(users, ['user', 'age']);
9949      * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
9950      */
9951     var sortBy = baseRest(function(collection, iteratees) {
9952       if (collection == null) {
9953         return [];
9954       }
9955       var length = iteratees.length;
9956       if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
9957         iteratees = [];
9958       } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
9959         iteratees = [iteratees[0]];
9960       }
9961       return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
9962     });
9963
9964     /*------------------------------------------------------------------------*/
9965
9966     /**
9967      * Gets the timestamp of the number of milliseconds that have elapsed since
9968      * the Unix epoch (1 January 1970 00:00:00 UTC).
9969      *
9970      * @static
9971      * @memberOf _
9972      * @since 2.4.0
9973      * @category Date
9974      * @returns {number} Returns the timestamp.
9975      * @example
9976      *
9977      * _.defer(function(stamp) {
9978      *   console.log(_.now() - stamp);
9979      * }, _.now());
9980      * // => Logs the number of milliseconds it took for the deferred invocation.
9981      */
9982     var now = ctxNow || function() {
9983       return root.Date.now();
9984     };
9985
9986     /*------------------------------------------------------------------------*/
9987
9988     /**
9989      * The opposite of `_.before`; this method creates a function that invokes
9990      * `func` once it's called `n` or more times.
9991      *
9992      * @static
9993      * @memberOf _
9994      * @since 0.1.0
9995      * @category Function
9996      * @param {number} n The number of calls before `func` is invoked.
9997      * @param {Function} func The function to restrict.
9998      * @returns {Function} Returns the new restricted function.
9999      * @example
10000      *
10001      * var saves = ['profile', 'settings'];
10002      *
10003      * var done = _.after(saves.length, function() {
10004      *   console.log('done saving!');
10005      * });
10006      *
10007      * _.forEach(saves, function(type) {
10008      *   asyncSave({ 'type': type, 'complete': done });
10009      * });
10010      * // => Logs 'done saving!' after the two async saves have completed.
10011      */
10012     function after(n, func) {
10013       if (typeof func != 'function') {
10014         throw new TypeError(FUNC_ERROR_TEXT);
10015       }
10016       n = toInteger(n);
10017       return function() {
10018         if (--n < 1) {
10019           return func.apply(this, arguments);
10020         }
10021       };
10022     }
10023
10024     /**
10025      * Creates a function that invokes `func`, with up to `n` arguments,
10026      * ignoring any additional arguments.
10027      *
10028      * @static
10029      * @memberOf _
10030      * @since 3.0.0
10031      * @category Function
10032      * @param {Function} func The function to cap arguments for.
10033      * @param {number} [n=func.length] The arity cap.
10034      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10035      * @returns {Function} Returns the new capped function.
10036      * @example
10037      *
10038      * _.map(['6', '8', '10'], _.ary(parseInt, 1));
10039      * // => [6, 8, 10]
10040      */
10041     function ary(func, n, guard) {
10042       n = guard ? undefined : n;
10043       n = (func && n == null) ? func.length : n;
10044       return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
10045     }
10046
10047     /**
10048      * Creates a function that invokes `func`, with the `this` binding and arguments
10049      * of the created function, while it's called less than `n` times. Subsequent
10050      * calls to the created function return the result of the last `func` invocation.
10051      *
10052      * @static
10053      * @memberOf _
10054      * @since 3.0.0
10055      * @category Function
10056      * @param {number} n The number of calls at which `func` is no longer invoked.
10057      * @param {Function} func The function to restrict.
10058      * @returns {Function} Returns the new restricted function.
10059      * @example
10060      *
10061      * jQuery(element).on('click', _.before(5, addContactToList));
10062      * // => Allows adding up to 4 contacts to the list.
10063      */
10064     function before(n, func) {
10065       var result;
10066       if (typeof func != 'function') {
10067         throw new TypeError(FUNC_ERROR_TEXT);
10068       }
10069       n = toInteger(n);
10070       return function() {
10071         if (--n > 0) {
10072           result = func.apply(this, arguments);
10073         }
10074         if (n <= 1) {
10075           func = undefined;
10076         }
10077         return result;
10078       };
10079     }
10080
10081     /**
10082      * Creates a function that invokes `func` with the `this` binding of `thisArg`
10083      * and `partials` prepended to the arguments it receives.
10084      *
10085      * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
10086      * may be used as a placeholder for partially applied arguments.
10087      *
10088      * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
10089      * property of bound functions.
10090      *
10091      * @static
10092      * @memberOf _
10093      * @since 0.1.0
10094      * @category Function
10095      * @param {Function} func The function to bind.
10096      * @param {*} thisArg The `this` binding of `func`.
10097      * @param {...*} [partials] The arguments to be partially applied.
10098      * @returns {Function} Returns the new bound function.
10099      * @example
10100      *
10101      * function greet(greeting, punctuation) {
10102      *   return greeting + ' ' + this.user + punctuation;
10103      * }
10104      *
10105      * var object = { 'user': 'fred' };
10106      *
10107      * var bound = _.bind(greet, object, 'hi');
10108      * bound('!');
10109      * // => 'hi fred!'
10110      *
10111      * // Bound with placeholders.
10112      * var bound = _.bind(greet, object, _, '!');
10113      * bound('hi');
10114      * // => 'hi fred!'
10115      */
10116     var bind = baseRest(function(func, thisArg, partials) {
10117       var bitmask = WRAP_BIND_FLAG;
10118       if (partials.length) {
10119         var holders = replaceHolders(partials, getHolder(bind));
10120         bitmask |= WRAP_PARTIAL_FLAG;
10121       }
10122       return createWrap(func, bitmask, thisArg, partials, holders);
10123     });
10124
10125     /**
10126      * Creates a function that invokes the method at `object[key]` with `partials`
10127      * prepended to the arguments it receives.
10128      *
10129      * This method differs from `_.bind` by allowing bound functions to reference
10130      * methods that may be redefined or don't yet exist. See
10131      * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
10132      * for more details.
10133      *
10134      * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
10135      * builds, may be used as a placeholder for partially applied arguments.
10136      *
10137      * @static
10138      * @memberOf _
10139      * @since 0.10.0
10140      * @category Function
10141      * @param {Object} object The object to invoke the method on.
10142      * @param {string} key The key of the method.
10143      * @param {...*} [partials] The arguments to be partially applied.
10144      * @returns {Function} Returns the new bound function.
10145      * @example
10146      *
10147      * var object = {
10148      *   'user': 'fred',
10149      *   'greet': function(greeting, punctuation) {
10150      *     return greeting + ' ' + this.user + punctuation;
10151      *   }
10152      * };
10153      *
10154      * var bound = _.bindKey(object, 'greet', 'hi');
10155      * bound('!');
10156      * // => 'hi fred!'
10157      *
10158      * object.greet = function(greeting, punctuation) {
10159      *   return greeting + 'ya ' + this.user + punctuation;
10160      * };
10161      *
10162      * bound('!');
10163      * // => 'hiya fred!'
10164      *
10165      * // Bound with placeholders.
10166      * var bound = _.bindKey(object, 'greet', _, '!');
10167      * bound('hi');
10168      * // => 'hiya fred!'
10169      */
10170     var bindKey = baseRest(function(object, key, partials) {
10171       var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
10172       if (partials.length) {
10173         var holders = replaceHolders(partials, getHolder(bindKey));
10174         bitmask |= WRAP_PARTIAL_FLAG;
10175       }
10176       return createWrap(key, bitmask, object, partials, holders);
10177     });
10178
10179     /**
10180      * Creates a function that accepts arguments of `func` and either invokes
10181      * `func` returning its result, if at least `arity` number of arguments have
10182      * been provided, or returns a function that accepts the remaining `func`
10183      * arguments, and so on. The arity of `func` may be specified if `func.length`
10184      * is not sufficient.
10185      *
10186      * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
10187      * may be used as a placeholder for provided arguments.
10188      *
10189      * **Note:** This method doesn't set the "length" property of curried functions.
10190      *
10191      * @static
10192      * @memberOf _
10193      * @since 2.0.0
10194      * @category Function
10195      * @param {Function} func The function to curry.
10196      * @param {number} [arity=func.length] The arity of `func`.
10197      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10198      * @returns {Function} Returns the new curried function.
10199      * @example
10200      *
10201      * var abc = function(a, b, c) {
10202      *   return [a, b, c];
10203      * };
10204      *
10205      * var curried = _.curry(abc);
10206      *
10207      * curried(1)(2)(3);
10208      * // => [1, 2, 3]
10209      *
10210      * curried(1, 2)(3);
10211      * // => [1, 2, 3]
10212      *
10213      * curried(1, 2, 3);
10214      * // => [1, 2, 3]
10215      *
10216      * // Curried with placeholders.
10217      * curried(1)(_, 3)(2);
10218      * // => [1, 2, 3]
10219      */
10220     function curry(func, arity, guard) {
10221       arity = guard ? undefined : arity;
10222       var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10223       result.placeholder = curry.placeholder;
10224       return result;
10225     }
10226
10227     /**
10228      * This method is like `_.curry` except that arguments are applied to `func`
10229      * in the manner of `_.partialRight` instead of `_.partial`.
10230      *
10231      * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
10232      * builds, may be used as a placeholder for provided arguments.
10233      *
10234      * **Note:** This method doesn't set the "length" property of curried functions.
10235      *
10236      * @static
10237      * @memberOf _
10238      * @since 3.0.0
10239      * @category Function
10240      * @param {Function} func The function to curry.
10241      * @param {number} [arity=func.length] The arity of `func`.
10242      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10243      * @returns {Function} Returns the new curried function.
10244      * @example
10245      *
10246      * var abc = function(a, b, c) {
10247      *   return [a, b, c];
10248      * };
10249      *
10250      * var curried = _.curryRight(abc);
10251      *
10252      * curried(3)(2)(1);
10253      * // => [1, 2, 3]
10254      *
10255      * curried(2, 3)(1);
10256      * // => [1, 2, 3]
10257      *
10258      * curried(1, 2, 3);
10259      * // => [1, 2, 3]
10260      *
10261      * // Curried with placeholders.
10262      * curried(3)(1, _)(2);
10263      * // => [1, 2, 3]
10264      */
10265     function curryRight(func, arity, guard) {
10266       arity = guard ? undefined : arity;
10267       var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10268       result.placeholder = curryRight.placeholder;
10269       return result;
10270     }
10271
10272     /**
10273      * Creates a debounced function that delays invoking `func` until after `wait`
10274      * milliseconds have elapsed since the last time the debounced function was
10275      * invoked. The debounced function comes with a `cancel` method to cancel
10276      * delayed `func` invocations and a `flush` method to immediately invoke them.
10277      * Provide `options` to indicate whether `func` should be invoked on the
10278      * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
10279      * with the last arguments provided to the debounced function. Subsequent
10280      * calls to the debounced function return the result of the last `func`
10281      * invocation.
10282      *
10283      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10284      * invoked on the trailing edge of the timeout only if the debounced function
10285      * is invoked more than once during the `wait` timeout.
10286      *
10287      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10288      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10289      *
10290      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10291      * for details over the differences between `_.debounce` and `_.throttle`.
10292      *
10293      * @static
10294      * @memberOf _
10295      * @since 0.1.0
10296      * @category Function
10297      * @param {Function} func The function to debounce.
10298      * @param {number} [wait=0] The number of milliseconds to delay.
10299      * @param {Object} [options={}] The options object.
10300      * @param {boolean} [options.leading=false]
10301      *  Specify invoking on the leading edge of the timeout.
10302      * @param {number} [options.maxWait]
10303      *  The maximum time `func` is allowed to be delayed before it's invoked.
10304      * @param {boolean} [options.trailing=true]
10305      *  Specify invoking on the trailing edge of the timeout.
10306      * @returns {Function} Returns the new debounced function.
10307      * @example
10308      *
10309      * // Avoid costly calculations while the window size is in flux.
10310      * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
10311      *
10312      * // Invoke `sendMail` when clicked, debouncing subsequent calls.
10313      * jQuery(element).on('click', _.debounce(sendMail, 300, {
10314      *   'leading': true,
10315      *   'trailing': false
10316      * }));
10317      *
10318      * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
10319      * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
10320      * var source = new EventSource('/stream');
10321      * jQuery(source).on('message', debounced);
10322      *
10323      * // Cancel the trailing debounced invocation.
10324      * jQuery(window).on('popstate', debounced.cancel);
10325      */
10326     function debounce(func, wait, options) {
10327       var lastArgs,
10328           lastThis,
10329           maxWait,
10330           result,
10331           timerId,
10332           lastCallTime,
10333           lastInvokeTime = 0,
10334           leading = false,
10335           maxing = false,
10336           trailing = true;
10337
10338       if (typeof func != 'function') {
10339         throw new TypeError(FUNC_ERROR_TEXT);
10340       }
10341       wait = toNumber(wait) || 0;
10342       if (isObject(options)) {
10343         leading = !!options.leading;
10344         maxing = 'maxWait' in options;
10345         maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
10346         trailing = 'trailing' in options ? !!options.trailing : trailing;
10347       }
10348
10349       function invokeFunc(time) {
10350         var args = lastArgs,
10351             thisArg = lastThis;
10352
10353         lastArgs = lastThis = undefined;
10354         lastInvokeTime = time;
10355         result = func.apply(thisArg, args);
10356         return result;
10357       }
10358
10359       function leadingEdge(time) {
10360         // Reset any `maxWait` timer.
10361         lastInvokeTime = time;
10362         // Start the timer for the trailing edge.
10363         timerId = setTimeout(timerExpired, wait);
10364         // Invoke the leading edge.
10365         return leading ? invokeFunc(time) : result;
10366       }
10367
10368       function remainingWait(time) {
10369         var timeSinceLastCall = time - lastCallTime,
10370             timeSinceLastInvoke = time - lastInvokeTime,
10371             result = wait - timeSinceLastCall;
10372
10373         return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
10374       }
10375
10376       function shouldInvoke(time) {
10377         var timeSinceLastCall = time - lastCallTime,
10378             timeSinceLastInvoke = time - lastInvokeTime;
10379
10380         // Either this is the first call, activity has stopped and we're at the
10381         // trailing edge, the system time has gone backwards and we're treating
10382         // it as the trailing edge, or we've hit the `maxWait` limit.
10383         return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
10384           (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
10385       }
10386
10387       function timerExpired() {
10388         var time = now();
10389         if (shouldInvoke(time)) {
10390           return trailingEdge(time);
10391         }
10392         // Restart the timer.
10393         timerId = setTimeout(timerExpired, remainingWait(time));
10394       }
10395
10396       function trailingEdge(time) {
10397         timerId = undefined;
10398
10399         // Only invoke if we have `lastArgs` which means `func` has been
10400         // debounced at least once.
10401         if (trailing && lastArgs) {
10402           return invokeFunc(time);
10403         }
10404         lastArgs = lastThis = undefined;
10405         return result;
10406       }
10407
10408       function cancel() {
10409         if (timerId !== undefined) {
10410           clearTimeout(timerId);
10411         }
10412         lastInvokeTime = 0;
10413         lastArgs = lastCallTime = lastThis = timerId = undefined;
10414       }
10415
10416       function flush() {
10417         return timerId === undefined ? result : trailingEdge(now());
10418       }
10419
10420       function debounced() {
10421         var time = now(),
10422             isInvoking = shouldInvoke(time);
10423
10424         lastArgs = arguments;
10425         lastThis = this;
10426         lastCallTime = time;
10427
10428         if (isInvoking) {
10429           if (timerId === undefined) {
10430             return leadingEdge(lastCallTime);
10431           }
10432           if (maxing) {
10433             // Handle invocations in a tight loop.
10434             timerId = setTimeout(timerExpired, wait);
10435             return invokeFunc(lastCallTime);
10436           }
10437         }
10438         if (timerId === undefined) {
10439           timerId = setTimeout(timerExpired, wait);
10440         }
10441         return result;
10442       }
10443       debounced.cancel = cancel;
10444       debounced.flush = flush;
10445       return debounced;
10446     }
10447
10448     /**
10449      * Defers invoking the `func` until the current call stack has cleared. Any
10450      * additional arguments are provided to `func` when it's invoked.
10451      *
10452      * @static
10453      * @memberOf _
10454      * @since 0.1.0
10455      * @category Function
10456      * @param {Function} func The function to defer.
10457      * @param {...*} [args] The arguments to invoke `func` with.
10458      * @returns {number} Returns the timer id.
10459      * @example
10460      *
10461      * _.defer(function(text) {
10462      *   console.log(text);
10463      * }, 'deferred');
10464      * // => Logs 'deferred' after one millisecond.
10465      */
10466     var defer = baseRest(function(func, args) {
10467       return baseDelay(func, 1, args);
10468     });
10469
10470     /**
10471      * Invokes `func` after `wait` milliseconds. Any additional arguments are
10472      * provided to `func` when it's invoked.
10473      *
10474      * @static
10475      * @memberOf _
10476      * @since 0.1.0
10477      * @category Function
10478      * @param {Function} func The function to delay.
10479      * @param {number} wait The number of milliseconds to delay invocation.
10480      * @param {...*} [args] The arguments to invoke `func` with.
10481      * @returns {number} Returns the timer id.
10482      * @example
10483      *
10484      * _.delay(function(text) {
10485      *   console.log(text);
10486      * }, 1000, 'later');
10487      * // => Logs 'later' after one second.
10488      */
10489     var delay = baseRest(function(func, wait, args) {
10490       return baseDelay(func, toNumber(wait) || 0, args);
10491     });
10492
10493     /**
10494      * Creates a function that invokes `func` with arguments reversed.
10495      *
10496      * @static
10497      * @memberOf _
10498      * @since 4.0.0
10499      * @category Function
10500      * @param {Function} func The function to flip arguments for.
10501      * @returns {Function} Returns the new flipped function.
10502      * @example
10503      *
10504      * var flipped = _.flip(function() {
10505      *   return _.toArray(arguments);
10506      * });
10507      *
10508      * flipped('a', 'b', 'c', 'd');
10509      * // => ['d', 'c', 'b', 'a']
10510      */
10511     function flip(func) {
10512       return createWrap(func, WRAP_FLIP_FLAG);
10513     }
10514
10515     /**
10516      * Creates a function that memoizes the result of `func`. If `resolver` is
10517      * provided, it determines the cache key for storing the result based on the
10518      * arguments provided to the memoized function. By default, the first argument
10519      * provided to the memoized function is used as the map cache key. The `func`
10520      * is invoked with the `this` binding of the memoized function.
10521      *
10522      * **Note:** The cache is exposed as the `cache` property on the memoized
10523      * function. Its creation may be customized by replacing the `_.memoize.Cache`
10524      * constructor with one whose instances implement the
10525      * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
10526      * method interface of `clear`, `delete`, `get`, `has`, and `set`.
10527      *
10528      * @static
10529      * @memberOf _
10530      * @since 0.1.0
10531      * @category Function
10532      * @param {Function} func The function to have its output memoized.
10533      * @param {Function} [resolver] The function to resolve the cache key.
10534      * @returns {Function} Returns the new memoized function.
10535      * @example
10536      *
10537      * var object = { 'a': 1, 'b': 2 };
10538      * var other = { 'c': 3, 'd': 4 };
10539      *
10540      * var values = _.memoize(_.values);
10541      * values(object);
10542      * // => [1, 2]
10543      *
10544      * values(other);
10545      * // => [3, 4]
10546      *
10547      * object.a = 2;
10548      * values(object);
10549      * // => [1, 2]
10550      *
10551      * // Modify the result cache.
10552      * values.cache.set(object, ['a', 'b']);
10553      * values(object);
10554      * // => ['a', 'b']
10555      *
10556      * // Replace `_.memoize.Cache`.
10557      * _.memoize.Cache = WeakMap;
10558      */
10559     function memoize(func, resolver) {
10560       if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
10561         throw new TypeError(FUNC_ERROR_TEXT);
10562       }
10563       var memoized = function() {
10564         var args = arguments,
10565             key = resolver ? resolver.apply(this, args) : args[0],
10566             cache = memoized.cache;
10567
10568         if (cache.has(key)) {
10569           return cache.get(key);
10570         }
10571         var result = func.apply(this, args);
10572         memoized.cache = cache.set(key, result) || cache;
10573         return result;
10574       };
10575       memoized.cache = new (memoize.Cache || MapCache);
10576       return memoized;
10577     }
10578
10579     // Expose `MapCache`.
10580     memoize.Cache = MapCache;
10581
10582     /**
10583      * Creates a function that negates the result of the predicate `func`. The
10584      * `func` predicate is invoked with the `this` binding and arguments of the
10585      * created function.
10586      *
10587      * @static
10588      * @memberOf _
10589      * @since 3.0.0
10590      * @category Function
10591      * @param {Function} predicate The predicate to negate.
10592      * @returns {Function} Returns the new negated function.
10593      * @example
10594      *
10595      * function isEven(n) {
10596      *   return n % 2 == 0;
10597      * }
10598      *
10599      * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
10600      * // => [1, 3, 5]
10601      */
10602     function negate(predicate) {
10603       if (typeof predicate != 'function') {
10604         throw new TypeError(FUNC_ERROR_TEXT);
10605       }
10606       return function() {
10607         var args = arguments;
10608         switch (args.length) {
10609           case 0: return !predicate.call(this);
10610           case 1: return !predicate.call(this, args[0]);
10611           case 2: return !predicate.call(this, args[0], args[1]);
10612           case 3: return !predicate.call(this, args[0], args[1], args[2]);
10613         }
10614         return !predicate.apply(this, args);
10615       };
10616     }
10617
10618     /**
10619      * Creates a function that is restricted to invoking `func` once. Repeat calls
10620      * to the function return the value of the first invocation. The `func` is
10621      * invoked with the `this` binding and arguments of the created function.
10622      *
10623      * @static
10624      * @memberOf _
10625      * @since 0.1.0
10626      * @category Function
10627      * @param {Function} func The function to restrict.
10628      * @returns {Function} Returns the new restricted function.
10629      * @example
10630      *
10631      * var initialize = _.once(createApplication);
10632      * initialize();
10633      * initialize();
10634      * // => `createApplication` is invoked once
10635      */
10636     function once(func) {
10637       return before(2, func);
10638     }
10639
10640     /**
10641      * Creates a function that invokes `func` with its arguments transformed.
10642      *
10643      * @static
10644      * @since 4.0.0
10645      * @memberOf _
10646      * @category Function
10647      * @param {Function} func The function to wrap.
10648      * @param {...(Function|Function[])} [transforms=[_.identity]]
10649      *  The argument transforms.
10650      * @returns {Function} Returns the new function.
10651      * @example
10652      *
10653      * function doubled(n) {
10654      *   return n * 2;
10655      * }
10656      *
10657      * function square(n) {
10658      *   return n * n;
10659      * }
10660      *
10661      * var func = _.overArgs(function(x, y) {
10662      *   return [x, y];
10663      * }, [square, doubled]);
10664      *
10665      * func(9, 3);
10666      * // => [81, 6]
10667      *
10668      * func(10, 5);
10669      * // => [100, 10]
10670      */
10671     var overArgs = castRest(function(func, transforms) {
10672       transforms = (transforms.length == 1 && isArray(transforms[0]))
10673         ? arrayMap(transforms[0], baseUnary(getIteratee()))
10674         : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
10675
10676       var funcsLength = transforms.length;
10677       return baseRest(function(args) {
10678         var index = -1,
10679             length = nativeMin(args.length, funcsLength);
10680
10681         while (++index < length) {
10682           args[index] = transforms[index].call(this, args[index]);
10683         }
10684         return apply(func, this, args);
10685       });
10686     });
10687
10688     /**
10689      * Creates a function that invokes `func` with `partials` prepended to the
10690      * arguments it receives. This method is like `_.bind` except it does **not**
10691      * alter the `this` binding.
10692      *
10693      * The `_.partial.placeholder` value, which defaults to `_` in monolithic
10694      * builds, may be used as a placeholder for partially applied arguments.
10695      *
10696      * **Note:** This method doesn't set the "length" property of partially
10697      * applied functions.
10698      *
10699      * @static
10700      * @memberOf _
10701      * @since 0.2.0
10702      * @category Function
10703      * @param {Function} func The function to partially apply arguments to.
10704      * @param {...*} [partials] The arguments to be partially applied.
10705      * @returns {Function} Returns the new partially applied function.
10706      * @example
10707      *
10708      * function greet(greeting, name) {
10709      *   return greeting + ' ' + name;
10710      * }
10711      *
10712      * var sayHelloTo = _.partial(greet, 'hello');
10713      * sayHelloTo('fred');
10714      * // => 'hello fred'
10715      *
10716      * // Partially applied with placeholders.
10717      * var greetFred = _.partial(greet, _, 'fred');
10718      * greetFred('hi');
10719      * // => 'hi fred'
10720      */
10721     var partial = baseRest(function(func, partials) {
10722       var holders = replaceHolders(partials, getHolder(partial));
10723       return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
10724     });
10725
10726     /**
10727      * This method is like `_.partial` except that partially applied arguments
10728      * are appended to the arguments it receives.
10729      *
10730      * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
10731      * builds, may be used as a placeholder for partially applied arguments.
10732      *
10733      * **Note:** This method doesn't set the "length" property of partially
10734      * applied functions.
10735      *
10736      * @static
10737      * @memberOf _
10738      * @since 1.0.0
10739      * @category Function
10740      * @param {Function} func The function to partially apply arguments to.
10741      * @param {...*} [partials] The arguments to be partially applied.
10742      * @returns {Function} Returns the new partially applied function.
10743      * @example
10744      *
10745      * function greet(greeting, name) {
10746      *   return greeting + ' ' + name;
10747      * }
10748      *
10749      * var greetFred = _.partialRight(greet, 'fred');
10750      * greetFred('hi');
10751      * // => 'hi fred'
10752      *
10753      * // Partially applied with placeholders.
10754      * var sayHelloTo = _.partialRight(greet, 'hello', _);
10755      * sayHelloTo('fred');
10756      * // => 'hello fred'
10757      */
10758     var partialRight = baseRest(function(func, partials) {
10759       var holders = replaceHolders(partials, getHolder(partialRight));
10760       return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
10761     });
10762
10763     /**
10764      * Creates a function that invokes `func` with arguments arranged according
10765      * to the specified `indexes` where the argument value at the first index is
10766      * provided as the first argument, the argument value at the second index is
10767      * provided as the second argument, and so on.
10768      *
10769      * @static
10770      * @memberOf _
10771      * @since 3.0.0
10772      * @category Function
10773      * @param {Function} func The function to rearrange arguments for.
10774      * @param {...(number|number[])} indexes The arranged argument indexes.
10775      * @returns {Function} Returns the new function.
10776      * @example
10777      *
10778      * var rearged = _.rearg(function(a, b, c) {
10779      *   return [a, b, c];
10780      * }, [2, 0, 1]);
10781      *
10782      * rearged('b', 'c', 'a')
10783      * // => ['a', 'b', 'c']
10784      */
10785     var rearg = flatRest(function(func, indexes) {
10786       return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
10787     });
10788
10789     /**
10790      * Creates a function that invokes `func` with the `this` binding of the
10791      * created function and arguments from `start` and beyond provided as
10792      * an array.
10793      *
10794      * **Note:** This method is based on the
10795      * [rest parameter](https://mdn.io/rest_parameters).
10796      *
10797      * @static
10798      * @memberOf _
10799      * @since 4.0.0
10800      * @category Function
10801      * @param {Function} func The function to apply a rest parameter to.
10802      * @param {number} [start=func.length-1] The start position of the rest parameter.
10803      * @returns {Function} Returns the new function.
10804      * @example
10805      *
10806      * var say = _.rest(function(what, names) {
10807      *   return what + ' ' + _.initial(names).join(', ') +
10808      *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
10809      * });
10810      *
10811      * say('hello', 'fred', 'barney', 'pebbles');
10812      * // => 'hello fred, barney, & pebbles'
10813      */
10814     function rest(func, start) {
10815       if (typeof func != 'function') {
10816         throw new TypeError(FUNC_ERROR_TEXT);
10817       }
10818       start = start === undefined ? start : toInteger(start);
10819       return baseRest(func, start);
10820     }
10821
10822     /**
10823      * Creates a function that invokes `func` with the `this` binding of the
10824      * create function and an array of arguments much like
10825      * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
10826      *
10827      * **Note:** This method is based on the
10828      * [spread operator](https://mdn.io/spread_operator).
10829      *
10830      * @static
10831      * @memberOf _
10832      * @since 3.2.0
10833      * @category Function
10834      * @param {Function} func The function to spread arguments over.
10835      * @param {number} [start=0] The start position of the spread.
10836      * @returns {Function} Returns the new function.
10837      * @example
10838      *
10839      * var say = _.spread(function(who, what) {
10840      *   return who + ' says ' + what;
10841      * });
10842      *
10843      * say(['fred', 'hello']);
10844      * // => 'fred says hello'
10845      *
10846      * var numbers = Promise.all([
10847      *   Promise.resolve(40),
10848      *   Promise.resolve(36)
10849      * ]);
10850      *
10851      * numbers.then(_.spread(function(x, y) {
10852      *   return x + y;
10853      * }));
10854      * // => a Promise of 76
10855      */
10856     function spread(func, start) {
10857       if (typeof func != 'function') {
10858         throw new TypeError(FUNC_ERROR_TEXT);
10859       }
10860       start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
10861       return baseRest(function(args) {
10862         var array = args[start],
10863             otherArgs = castSlice(args, 0, start);
10864
10865         if (array) {
10866           arrayPush(otherArgs, array);
10867         }
10868         return apply(func, this, otherArgs);
10869       });
10870     }
10871
10872     /**
10873      * Creates a throttled function that only invokes `func` at most once per
10874      * every `wait` milliseconds. The throttled function comes with a `cancel`
10875      * method to cancel delayed `func` invocations and a `flush` method to
10876      * immediately invoke them. Provide `options` to indicate whether `func`
10877      * should be invoked on the leading and/or trailing edge of the `wait`
10878      * timeout. The `func` is invoked with the last arguments provided to the
10879      * throttled function. Subsequent calls to the throttled function return the
10880      * result of the last `func` invocation.
10881      *
10882      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10883      * invoked on the trailing edge of the timeout only if the throttled function
10884      * is invoked more than once during the `wait` timeout.
10885      *
10886      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10887      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10888      *
10889      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10890      * for details over the differences between `_.throttle` and `_.debounce`.
10891      *
10892      * @static
10893      * @memberOf _
10894      * @since 0.1.0
10895      * @category Function
10896      * @param {Function} func The function to throttle.
10897      * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
10898      * @param {Object} [options={}] The options object.
10899      * @param {boolean} [options.leading=true]
10900      *  Specify invoking on the leading edge of the timeout.
10901      * @param {boolean} [options.trailing=true]
10902      *  Specify invoking on the trailing edge of the timeout.
10903      * @returns {Function} Returns the new throttled function.
10904      * @example
10905      *
10906      * // Avoid excessively updating the position while scrolling.
10907      * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
10908      *
10909      * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
10910      * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
10911      * jQuery(element).on('click', throttled);
10912      *
10913      * // Cancel the trailing throttled invocation.
10914      * jQuery(window).on('popstate', throttled.cancel);
10915      */
10916     function throttle(func, wait, options) {
10917       var leading = true,
10918           trailing = true;
10919
10920       if (typeof func != 'function') {
10921         throw new TypeError(FUNC_ERROR_TEXT);
10922       }
10923       if (isObject(options)) {
10924         leading = 'leading' in options ? !!options.leading : leading;
10925         trailing = 'trailing' in options ? !!options.trailing : trailing;
10926       }
10927       return debounce(func, wait, {
10928         'leading': leading,
10929         'maxWait': wait,
10930         'trailing': trailing
10931       });
10932     }
10933
10934     /**
10935      * Creates a function that accepts up to one argument, ignoring any
10936      * additional arguments.
10937      *
10938      * @static
10939      * @memberOf _
10940      * @since 4.0.0
10941      * @category Function
10942      * @param {Function} func The function to cap arguments for.
10943      * @returns {Function} Returns the new capped function.
10944      * @example
10945      *
10946      * _.map(['6', '8', '10'], _.unary(parseInt));
10947      * // => [6, 8, 10]
10948      */
10949     function unary(func) {
10950       return ary(func, 1);
10951     }
10952
10953     /**
10954      * Creates a function that provides `value` to `wrapper` as its first
10955      * argument. Any additional arguments provided to the function are appended
10956      * to those provided to the `wrapper`. The wrapper is invoked with the `this`
10957      * binding of the created function.
10958      *
10959      * @static
10960      * @memberOf _
10961      * @since 0.1.0
10962      * @category Function
10963      * @param {*} value The value to wrap.
10964      * @param {Function} [wrapper=identity] The wrapper function.
10965      * @returns {Function} Returns the new function.
10966      * @example
10967      *
10968      * var p = _.wrap(_.escape, function(func, text) {
10969      *   return '<p>' + func(text) + '</p>';
10970      * });
10971      *
10972      * p('fred, barney, & pebbles');
10973      * // => '<p>fred, barney, &amp; pebbles</p>'
10974      */
10975     function wrap(value, wrapper) {
10976       return partial(castFunction(wrapper), value);
10977     }
10978
10979     /*------------------------------------------------------------------------*/
10980
10981     /**
10982      * Casts `value` as an array if it's not one.
10983      *
10984      * @static
10985      * @memberOf _
10986      * @since 4.4.0
10987      * @category Lang
10988      * @param {*} value The value to inspect.
10989      * @returns {Array} Returns the cast array.
10990      * @example
10991      *
10992      * _.castArray(1);
10993      * // => [1]
10994      *
10995      * _.castArray({ 'a': 1 });
10996      * // => [{ 'a': 1 }]
10997      *
10998      * _.castArray('abc');
10999      * // => ['abc']
11000      *
11001      * _.castArray(null);
11002      * // => [null]
11003      *
11004      * _.castArray(undefined);
11005      * // => [undefined]
11006      *
11007      * _.castArray();
11008      * // => []
11009      *
11010      * var array = [1, 2, 3];
11011      * console.log(_.castArray(array) === array);
11012      * // => true
11013      */
11014     function castArray() {
11015       if (!arguments.length) {
11016         return [];
11017       }
11018       var value = arguments[0];
11019       return isArray(value) ? value : [value];
11020     }
11021
11022     /**
11023      * Creates a shallow clone of `value`.
11024      *
11025      * **Note:** This method is loosely based on the
11026      * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
11027      * and supports cloning arrays, array buffers, booleans, date objects, maps,
11028      * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
11029      * arrays. The own enumerable properties of `arguments` objects are cloned
11030      * as plain objects. An empty object is returned for uncloneable values such
11031      * as error objects, functions, DOM nodes, and WeakMaps.
11032      *
11033      * @static
11034      * @memberOf _
11035      * @since 0.1.0
11036      * @category Lang
11037      * @param {*} value The value to clone.
11038      * @returns {*} Returns the cloned value.
11039      * @see _.cloneDeep
11040      * @example
11041      *
11042      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11043      *
11044      * var shallow = _.clone(objects);
11045      * console.log(shallow[0] === objects[0]);
11046      * // => true
11047      */
11048     function clone(value) {
11049       return baseClone(value, CLONE_SYMBOLS_FLAG);
11050     }
11051
11052     /**
11053      * This method is like `_.clone` except that it accepts `customizer` which
11054      * is invoked to produce the cloned value. If `customizer` returns `undefined`,
11055      * cloning is handled by the method instead. The `customizer` is invoked with
11056      * up to four arguments; (value [, index|key, object, stack]).
11057      *
11058      * @static
11059      * @memberOf _
11060      * @since 4.0.0
11061      * @category Lang
11062      * @param {*} value The value to clone.
11063      * @param {Function} [customizer] The function to customize cloning.
11064      * @returns {*} Returns the cloned value.
11065      * @see _.cloneDeepWith
11066      * @example
11067      *
11068      * function customizer(value) {
11069      *   if (_.isElement(value)) {
11070      *     return value.cloneNode(false);
11071      *   }
11072      * }
11073      *
11074      * var el = _.cloneWith(document.body, customizer);
11075      *
11076      * console.log(el === document.body);
11077      * // => false
11078      * console.log(el.nodeName);
11079      * // => 'BODY'
11080      * console.log(el.childNodes.length);
11081      * // => 0
11082      */
11083     function cloneWith(value, customizer) {
11084       customizer = typeof customizer == 'function' ? customizer : undefined;
11085       return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
11086     }
11087
11088     /**
11089      * This method is like `_.clone` except that it recursively clones `value`.
11090      *
11091      * @static
11092      * @memberOf _
11093      * @since 1.0.0
11094      * @category Lang
11095      * @param {*} value The value to recursively clone.
11096      * @returns {*} Returns the deep cloned value.
11097      * @see _.clone
11098      * @example
11099      *
11100      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11101      *
11102      * var deep = _.cloneDeep(objects);
11103      * console.log(deep[0] === objects[0]);
11104      * // => false
11105      */
11106     function cloneDeep(value) {
11107       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
11108     }
11109
11110     /**
11111      * This method is like `_.cloneWith` except that it recursively clones `value`.
11112      *
11113      * @static
11114      * @memberOf _
11115      * @since 4.0.0
11116      * @category Lang
11117      * @param {*} value The value to recursively clone.
11118      * @param {Function} [customizer] The function to customize cloning.
11119      * @returns {*} Returns the deep cloned value.
11120      * @see _.cloneWith
11121      * @example
11122      *
11123      * function customizer(value) {
11124      *   if (_.isElement(value)) {
11125      *     return value.cloneNode(true);
11126      *   }
11127      * }
11128      *
11129      * var el = _.cloneDeepWith(document.body, customizer);
11130      *
11131      * console.log(el === document.body);
11132      * // => false
11133      * console.log(el.nodeName);
11134      * // => 'BODY'
11135      * console.log(el.childNodes.length);
11136      * // => 20
11137      */
11138     function cloneDeepWith(value, customizer) {
11139       customizer = typeof customizer == 'function' ? customizer : undefined;
11140       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
11141     }
11142
11143     /**
11144      * Checks if `object` conforms to `source` by invoking the predicate
11145      * properties of `source` with the corresponding property values of `object`.
11146      *
11147      * **Note:** This method is equivalent to `_.conforms` when `source` is
11148      * partially applied.
11149      *
11150      * @static
11151      * @memberOf _
11152      * @since 4.14.0
11153      * @category Lang
11154      * @param {Object} object The object to inspect.
11155      * @param {Object} source The object of property predicates to conform to.
11156      * @returns {boolean} Returns `true` if `object` conforms, else `false`.
11157      * @example
11158      *
11159      * var object = { 'a': 1, 'b': 2 };
11160      *
11161      * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
11162      * // => true
11163      *
11164      * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
11165      * // => false
11166      */
11167     function conformsTo(object, source) {
11168       return source == null || baseConformsTo(object, source, keys(source));
11169     }
11170
11171     /**
11172      * Performs a
11173      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
11174      * comparison between two values to determine if they are equivalent.
11175      *
11176      * @static
11177      * @memberOf _
11178      * @since 4.0.0
11179      * @category Lang
11180      * @param {*} value The value to compare.
11181      * @param {*} other The other value to compare.
11182      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11183      * @example
11184      *
11185      * var object = { 'a': 1 };
11186      * var other = { 'a': 1 };
11187      *
11188      * _.eq(object, object);
11189      * // => true
11190      *
11191      * _.eq(object, other);
11192      * // => false
11193      *
11194      * _.eq('a', 'a');
11195      * // => true
11196      *
11197      * _.eq('a', Object('a'));
11198      * // => false
11199      *
11200      * _.eq(NaN, NaN);
11201      * // => true
11202      */
11203     function eq(value, other) {
11204       return value === other || (value !== value && other !== other);
11205     }
11206
11207     /**
11208      * Checks if `value` is greater than `other`.
11209      *
11210      * @static
11211      * @memberOf _
11212      * @since 3.9.0
11213      * @category Lang
11214      * @param {*} value The value to compare.
11215      * @param {*} other The other value to compare.
11216      * @returns {boolean} Returns `true` if `value` is greater than `other`,
11217      *  else `false`.
11218      * @see _.lt
11219      * @example
11220      *
11221      * _.gt(3, 1);
11222      * // => true
11223      *
11224      * _.gt(3, 3);
11225      * // => false
11226      *
11227      * _.gt(1, 3);
11228      * // => false
11229      */
11230     var gt = createRelationalOperation(baseGt);
11231
11232     /**
11233      * Checks if `value` is greater than or equal to `other`.
11234      *
11235      * @static
11236      * @memberOf _
11237      * @since 3.9.0
11238      * @category Lang
11239      * @param {*} value The value to compare.
11240      * @param {*} other The other value to compare.
11241      * @returns {boolean} Returns `true` if `value` is greater than or equal to
11242      *  `other`, else `false`.
11243      * @see _.lte
11244      * @example
11245      *
11246      * _.gte(3, 1);
11247      * // => true
11248      *
11249      * _.gte(3, 3);
11250      * // => true
11251      *
11252      * _.gte(1, 3);
11253      * // => false
11254      */
11255     var gte = createRelationalOperation(function(value, other) {
11256       return value >= other;
11257     });
11258
11259     /**
11260      * Checks if `value` is likely an `arguments` object.
11261      *
11262      * @static
11263      * @memberOf _
11264      * @since 0.1.0
11265      * @category Lang
11266      * @param {*} value The value to check.
11267      * @returns {boolean} Returns `true` if `value` is an `arguments` object,
11268      *  else `false`.
11269      * @example
11270      *
11271      * _.isArguments(function() { return arguments; }());
11272      * // => true
11273      *
11274      * _.isArguments([1, 2, 3]);
11275      * // => false
11276      */
11277     var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
11278       return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
11279         !propertyIsEnumerable.call(value, 'callee');
11280     };
11281
11282     /**
11283      * Checks if `value` is classified as an `Array` object.
11284      *
11285      * @static
11286      * @memberOf _
11287      * @since 0.1.0
11288      * @category Lang
11289      * @param {*} value The value to check.
11290      * @returns {boolean} Returns `true` if `value` is an array, else `false`.
11291      * @example
11292      *
11293      * _.isArray([1, 2, 3]);
11294      * // => true
11295      *
11296      * _.isArray(document.body.children);
11297      * // => false
11298      *
11299      * _.isArray('abc');
11300      * // => false
11301      *
11302      * _.isArray(_.noop);
11303      * // => false
11304      */
11305     var isArray = Array.isArray;
11306
11307     /**
11308      * Checks if `value` is classified as an `ArrayBuffer` object.
11309      *
11310      * @static
11311      * @memberOf _
11312      * @since 4.3.0
11313      * @category Lang
11314      * @param {*} value The value to check.
11315      * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
11316      * @example
11317      *
11318      * _.isArrayBuffer(new ArrayBuffer(2));
11319      * // => true
11320      *
11321      * _.isArrayBuffer(new Array(2));
11322      * // => false
11323      */
11324     var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
11325
11326     /**
11327      * Checks if `value` is array-like. A value is considered array-like if it's
11328      * not a function and has a `value.length` that's an integer greater than or
11329      * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
11330      *
11331      * @static
11332      * @memberOf _
11333      * @since 4.0.0
11334      * @category Lang
11335      * @param {*} value The value to check.
11336      * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
11337      * @example
11338      *
11339      * _.isArrayLike([1, 2, 3]);
11340      * // => true
11341      *
11342      * _.isArrayLike(document.body.children);
11343      * // => true
11344      *
11345      * _.isArrayLike('abc');
11346      * // => true
11347      *
11348      * _.isArrayLike(_.noop);
11349      * // => false
11350      */
11351     function isArrayLike(value) {
11352       return value != null && isLength(value.length) && !isFunction(value);
11353     }
11354
11355     /**
11356      * This method is like `_.isArrayLike` except that it also checks if `value`
11357      * is an object.
11358      *
11359      * @static
11360      * @memberOf _
11361      * @since 4.0.0
11362      * @category Lang
11363      * @param {*} value The value to check.
11364      * @returns {boolean} Returns `true` if `value` is an array-like object,
11365      *  else `false`.
11366      * @example
11367      *
11368      * _.isArrayLikeObject([1, 2, 3]);
11369      * // => true
11370      *
11371      * _.isArrayLikeObject(document.body.children);
11372      * // => true
11373      *
11374      * _.isArrayLikeObject('abc');
11375      * // => false
11376      *
11377      * _.isArrayLikeObject(_.noop);
11378      * // => false
11379      */
11380     function isArrayLikeObject(value) {
11381       return isObjectLike(value) && isArrayLike(value);
11382     }
11383
11384     /**
11385      * Checks if `value` is classified as a boolean primitive or object.
11386      *
11387      * @static
11388      * @memberOf _
11389      * @since 0.1.0
11390      * @category Lang
11391      * @param {*} value The value to check.
11392      * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
11393      * @example
11394      *
11395      * _.isBoolean(false);
11396      * // => true
11397      *
11398      * _.isBoolean(null);
11399      * // => false
11400      */
11401     function isBoolean(value) {
11402       return value === true || value === false ||
11403         (isObjectLike(value) && baseGetTag(value) == boolTag);
11404     }
11405
11406     /**
11407      * Checks if `value` is a buffer.
11408      *
11409      * @static
11410      * @memberOf _
11411      * @since 4.3.0
11412      * @category Lang
11413      * @param {*} value The value to check.
11414      * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
11415      * @example
11416      *
11417      * _.isBuffer(new Buffer(2));
11418      * // => true
11419      *
11420      * _.isBuffer(new Uint8Array(2));
11421      * // => false
11422      */
11423     var isBuffer = nativeIsBuffer || stubFalse;
11424
11425     /**
11426      * Checks if `value` is classified as a `Date` object.
11427      *
11428      * @static
11429      * @memberOf _
11430      * @since 0.1.0
11431      * @category Lang
11432      * @param {*} value The value to check.
11433      * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
11434      * @example
11435      *
11436      * _.isDate(new Date);
11437      * // => true
11438      *
11439      * _.isDate('Mon April 23 2012');
11440      * // => false
11441      */
11442     var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
11443
11444     /**
11445      * Checks if `value` is likely a DOM element.
11446      *
11447      * @static
11448      * @memberOf _
11449      * @since 0.1.0
11450      * @category Lang
11451      * @param {*} value The value to check.
11452      * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
11453      * @example
11454      *
11455      * _.isElement(document.body);
11456      * // => true
11457      *
11458      * _.isElement('<body>');
11459      * // => false
11460      */
11461     function isElement(value) {
11462       return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
11463     }
11464
11465     /**
11466      * Checks if `value` is an empty object, collection, map, or set.
11467      *
11468      * Objects are considered empty if they have no own enumerable string keyed
11469      * properties.
11470      *
11471      * Array-like values such as `arguments` objects, arrays, buffers, strings, or
11472      * jQuery-like collections are considered empty if they have a `length` of `0`.
11473      * Similarly, maps and sets are considered empty if they have a `size` of `0`.
11474      *
11475      * @static
11476      * @memberOf _
11477      * @since 0.1.0
11478      * @category Lang
11479      * @param {*} value The value to check.
11480      * @returns {boolean} Returns `true` if `value` is empty, else `false`.
11481      * @example
11482      *
11483      * _.isEmpty(null);
11484      * // => true
11485      *
11486      * _.isEmpty(true);
11487      * // => true
11488      *
11489      * _.isEmpty(1);
11490      * // => true
11491      *
11492      * _.isEmpty([1, 2, 3]);
11493      * // => false
11494      *
11495      * _.isEmpty({ 'a': 1 });
11496      * // => false
11497      */
11498     function isEmpty(value) {
11499       if (value == null) {
11500         return true;
11501       }
11502       if (isArrayLike(value) &&
11503           (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
11504             isBuffer(value) || isTypedArray(value) || isArguments(value))) {
11505         return !value.length;
11506       }
11507       var tag = getTag(value);
11508       if (tag == mapTag || tag == setTag) {
11509         return !value.size;
11510       }
11511       if (isPrototype(value)) {
11512         return !baseKeys(value).length;
11513       }
11514       for (var key in value) {
11515         if (hasOwnProperty.call(value, key)) {
11516           return false;
11517         }
11518       }
11519       return true;
11520     }
11521
11522     /**
11523      * Performs a deep comparison between two values to determine if they are
11524      * equivalent.
11525      *
11526      * **Note:** This method supports comparing arrays, array buffers, booleans,
11527      * date objects, error objects, maps, numbers, `Object` objects, regexes,
11528      * sets, strings, symbols, and typed arrays. `Object` objects are compared
11529      * by their own, not inherited, enumerable properties. Functions and DOM
11530      * nodes are **not** supported.
11531      *
11532      * @static
11533      * @memberOf _
11534      * @since 0.1.0
11535      * @category Lang
11536      * @param {*} value The value to compare.
11537      * @param {*} other The other value to compare.
11538      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11539      * @example
11540      *
11541      * var object = { 'a': 1 };
11542      * var other = { 'a': 1 };
11543      *
11544      * _.isEqual(object, other);
11545      * // => true
11546      *
11547      * object === other;
11548      * // => false
11549      */
11550     function isEqual(value, other) {
11551       return baseIsEqual(value, other);
11552     }
11553
11554     /**
11555      * This method is like `_.isEqual` except that it accepts `customizer` which
11556      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11557      * are handled by the method instead. The `customizer` is invoked with up to
11558      * six arguments: (objValue, othValue [, index|key, object, other, stack]).
11559      *
11560      * @static
11561      * @memberOf _
11562      * @since 4.0.0
11563      * @category Lang
11564      * @param {*} value The value to compare.
11565      * @param {*} other The other value to compare.
11566      * @param {Function} [customizer] The function to customize comparisons.
11567      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11568      * @example
11569      *
11570      * function isGreeting(value) {
11571      *   return /^h(?:i|ello)$/.test(value);
11572      * }
11573      *
11574      * function customizer(objValue, othValue) {
11575      *   if (isGreeting(objValue) && isGreeting(othValue)) {
11576      *     return true;
11577      *   }
11578      * }
11579      *
11580      * var array = ['hello', 'goodbye'];
11581      * var other = ['hi', 'goodbye'];
11582      *
11583      * _.isEqualWith(array, other, customizer);
11584      * // => true
11585      */
11586     function isEqualWith(value, other, customizer) {
11587       customizer = typeof customizer == 'function' ? customizer : undefined;
11588       var result = customizer ? customizer(value, other) : undefined;
11589       return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
11590     }
11591
11592     /**
11593      * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
11594      * `SyntaxError`, `TypeError`, or `URIError` object.
11595      *
11596      * @static
11597      * @memberOf _
11598      * @since 3.0.0
11599      * @category Lang
11600      * @param {*} value The value to check.
11601      * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
11602      * @example
11603      *
11604      * _.isError(new Error);
11605      * // => true
11606      *
11607      * _.isError(Error);
11608      * // => false
11609      */
11610     function isError(value) {
11611       if (!isObjectLike(value)) {
11612         return false;
11613       }
11614       var tag = baseGetTag(value);
11615       return tag == errorTag || tag == domExcTag ||
11616         (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
11617     }
11618
11619     /**
11620      * Checks if `value` is a finite primitive number.
11621      *
11622      * **Note:** This method is based on
11623      * [`Number.isFinite`](https://mdn.io/Number/isFinite).
11624      *
11625      * @static
11626      * @memberOf _
11627      * @since 0.1.0
11628      * @category Lang
11629      * @param {*} value The value to check.
11630      * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
11631      * @example
11632      *
11633      * _.isFinite(3);
11634      * // => true
11635      *
11636      * _.isFinite(Number.MIN_VALUE);
11637      * // => true
11638      *
11639      * _.isFinite(Infinity);
11640      * // => false
11641      *
11642      * _.isFinite('3');
11643      * // => false
11644      */
11645     function isFinite(value) {
11646       return typeof value == 'number' && nativeIsFinite(value);
11647     }
11648
11649     /**
11650      * Checks if `value` is classified as a `Function` object.
11651      *
11652      * @static
11653      * @memberOf _
11654      * @since 0.1.0
11655      * @category Lang
11656      * @param {*} value The value to check.
11657      * @returns {boolean} Returns `true` if `value` is a function, else `false`.
11658      * @example
11659      *
11660      * _.isFunction(_);
11661      * // => true
11662      *
11663      * _.isFunction(/abc/);
11664      * // => false
11665      */
11666     function isFunction(value) {
11667       if (!isObject(value)) {
11668         return false;
11669       }
11670       // The use of `Object#toString` avoids issues with the `typeof` operator
11671       // in Safari 9 which returns 'object' for typed arrays and other constructors.
11672       var tag = baseGetTag(value);
11673       return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
11674     }
11675
11676     /**
11677      * Checks if `value` is an integer.
11678      *
11679      * **Note:** This method is based on
11680      * [`Number.isInteger`](https://mdn.io/Number/isInteger).
11681      *
11682      * @static
11683      * @memberOf _
11684      * @since 4.0.0
11685      * @category Lang
11686      * @param {*} value The value to check.
11687      * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
11688      * @example
11689      *
11690      * _.isInteger(3);
11691      * // => true
11692      *
11693      * _.isInteger(Number.MIN_VALUE);
11694      * // => false
11695      *
11696      * _.isInteger(Infinity);
11697      * // => false
11698      *
11699      * _.isInteger('3');
11700      * // => false
11701      */
11702     function isInteger(value) {
11703       return typeof value == 'number' && value == toInteger(value);
11704     }
11705
11706     /**
11707      * Checks if `value` is a valid array-like length.
11708      *
11709      * **Note:** This method is loosely based on
11710      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
11711      *
11712      * @static
11713      * @memberOf _
11714      * @since 4.0.0
11715      * @category Lang
11716      * @param {*} value The value to check.
11717      * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
11718      * @example
11719      *
11720      * _.isLength(3);
11721      * // => true
11722      *
11723      * _.isLength(Number.MIN_VALUE);
11724      * // => false
11725      *
11726      * _.isLength(Infinity);
11727      * // => false
11728      *
11729      * _.isLength('3');
11730      * // => false
11731      */
11732     function isLength(value) {
11733       return typeof value == 'number' &&
11734         value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
11735     }
11736
11737     /**
11738      * Checks if `value` is the
11739      * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
11740      * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
11741      *
11742      * @static
11743      * @memberOf _
11744      * @since 0.1.0
11745      * @category Lang
11746      * @param {*} value The value to check.
11747      * @returns {boolean} Returns `true` if `value` is an object, else `false`.
11748      * @example
11749      *
11750      * _.isObject({});
11751      * // => true
11752      *
11753      * _.isObject([1, 2, 3]);
11754      * // => true
11755      *
11756      * _.isObject(_.noop);
11757      * // => true
11758      *
11759      * _.isObject(null);
11760      * // => false
11761      */
11762     function isObject(value) {
11763       var type = typeof value;
11764       return value != null && (type == 'object' || type == 'function');
11765     }
11766
11767     /**
11768      * Checks if `value` is object-like. A value is object-like if it's not `null`
11769      * and has a `typeof` result of "object".
11770      *
11771      * @static
11772      * @memberOf _
11773      * @since 4.0.0
11774      * @category Lang
11775      * @param {*} value The value to check.
11776      * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
11777      * @example
11778      *
11779      * _.isObjectLike({});
11780      * // => true
11781      *
11782      * _.isObjectLike([1, 2, 3]);
11783      * // => true
11784      *
11785      * _.isObjectLike(_.noop);
11786      * // => false
11787      *
11788      * _.isObjectLike(null);
11789      * // => false
11790      */
11791     function isObjectLike(value) {
11792       return value != null && typeof value == 'object';
11793     }
11794
11795     /**
11796      * Checks if `value` is classified as a `Map` object.
11797      *
11798      * @static
11799      * @memberOf _
11800      * @since 4.3.0
11801      * @category Lang
11802      * @param {*} value The value to check.
11803      * @returns {boolean} Returns `true` if `value` is a map, else `false`.
11804      * @example
11805      *
11806      * _.isMap(new Map);
11807      * // => true
11808      *
11809      * _.isMap(new WeakMap);
11810      * // => false
11811      */
11812     var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
11813
11814     /**
11815      * Performs a partial deep comparison between `object` and `source` to
11816      * determine if `object` contains equivalent property values.
11817      *
11818      * **Note:** This method is equivalent to `_.matches` when `source` is
11819      * partially applied.
11820      *
11821      * Partial comparisons will match empty array and empty object `source`
11822      * values against any array or object value, respectively. See `_.isEqual`
11823      * for a list of supported value comparisons.
11824      *
11825      * @static
11826      * @memberOf _
11827      * @since 3.0.0
11828      * @category Lang
11829      * @param {Object} object The object to inspect.
11830      * @param {Object} source The object of property values to match.
11831      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11832      * @example
11833      *
11834      * var object = { 'a': 1, 'b': 2 };
11835      *
11836      * _.isMatch(object, { 'b': 2 });
11837      * // => true
11838      *
11839      * _.isMatch(object, { 'b': 1 });
11840      * // => false
11841      */
11842     function isMatch(object, source) {
11843       return object === source || baseIsMatch(object, source, getMatchData(source));
11844     }
11845
11846     /**
11847      * This method is like `_.isMatch` except that it accepts `customizer` which
11848      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11849      * are handled by the method instead. The `customizer` is invoked with five
11850      * arguments: (objValue, srcValue, index|key, object, source).
11851      *
11852      * @static
11853      * @memberOf _
11854      * @since 4.0.0
11855      * @category Lang
11856      * @param {Object} object The object to inspect.
11857      * @param {Object} source The object of property values to match.
11858      * @param {Function} [customizer] The function to customize comparisons.
11859      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11860      * @example
11861      *
11862      * function isGreeting(value) {
11863      *   return /^h(?:i|ello)$/.test(value);
11864      * }
11865      *
11866      * function customizer(objValue, srcValue) {
11867      *   if (isGreeting(objValue) && isGreeting(srcValue)) {
11868      *     return true;
11869      *   }
11870      * }
11871      *
11872      * var object = { 'greeting': 'hello' };
11873      * var source = { 'greeting': 'hi' };
11874      *
11875      * _.isMatchWith(object, source, customizer);
11876      * // => true
11877      */
11878     function isMatchWith(object, source, customizer) {
11879       customizer = typeof customizer == 'function' ? customizer : undefined;
11880       return baseIsMatch(object, source, getMatchData(source), customizer);
11881     }
11882
11883     /**
11884      * Checks if `value` is `NaN`.
11885      *
11886      * **Note:** This method is based on
11887      * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
11888      * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
11889      * `undefined` and other non-number values.
11890      *
11891      * @static
11892      * @memberOf _
11893      * @since 0.1.0
11894      * @category Lang
11895      * @param {*} value The value to check.
11896      * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
11897      * @example
11898      *
11899      * _.isNaN(NaN);
11900      * // => true
11901      *
11902      * _.isNaN(new Number(NaN));
11903      * // => true
11904      *
11905      * isNaN(undefined);
11906      * // => true
11907      *
11908      * _.isNaN(undefined);
11909      * // => false
11910      */
11911     function isNaN(value) {
11912       // An `NaN` primitive is the only value that is not equal to itself.
11913       // Perform the `toStringTag` check first to avoid errors with some
11914       // ActiveX objects in IE.
11915       return isNumber(value) && value != +value;
11916     }
11917
11918     /**
11919      * Checks if `value` is a pristine native function.
11920      *
11921      * **Note:** This method can't reliably detect native functions in the presence
11922      * of the core-js package because core-js circumvents this kind of detection.
11923      * Despite multiple requests, the core-js maintainer has made it clear: any
11924      * attempt to fix the detection will be obstructed. As a result, we're left
11925      * with little choice but to throw an error. Unfortunately, this also affects
11926      * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
11927      * which rely on core-js.
11928      *
11929      * @static
11930      * @memberOf _
11931      * @since 3.0.0
11932      * @category Lang
11933      * @param {*} value The value to check.
11934      * @returns {boolean} Returns `true` if `value` is a native function,
11935      *  else `false`.
11936      * @example
11937      *
11938      * _.isNative(Array.prototype.push);
11939      * // => true
11940      *
11941      * _.isNative(_);
11942      * // => false
11943      */
11944     function isNative(value) {
11945       if (isMaskable(value)) {
11946         throw new Error(CORE_ERROR_TEXT);
11947       }
11948       return baseIsNative(value);
11949     }
11950
11951     /**
11952      * Checks if `value` is `null`.
11953      *
11954      * @static
11955      * @memberOf _
11956      * @since 0.1.0
11957      * @category Lang
11958      * @param {*} value The value to check.
11959      * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
11960      * @example
11961      *
11962      * _.isNull(null);
11963      * // => true
11964      *
11965      * _.isNull(void 0);
11966      * // => false
11967      */
11968     function isNull(value) {
11969       return value === null;
11970     }
11971
11972     /**
11973      * Checks if `value` is `null` or `undefined`.
11974      *
11975      * @static
11976      * @memberOf _
11977      * @since 4.0.0
11978      * @category Lang
11979      * @param {*} value The value to check.
11980      * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
11981      * @example
11982      *
11983      * _.isNil(null);
11984      * // => true
11985      *
11986      * _.isNil(void 0);
11987      * // => true
11988      *
11989      * _.isNil(NaN);
11990      * // => false
11991      */
11992     function isNil(value) {
11993       return value == null;
11994     }
11995
11996     /**
11997      * Checks if `value` is classified as a `Number` primitive or object.
11998      *
11999      * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
12000      * classified as numbers, use the `_.isFinite` method.
12001      *
12002      * @static
12003      * @memberOf _
12004      * @since 0.1.0
12005      * @category Lang
12006      * @param {*} value The value to check.
12007      * @returns {boolean} Returns `true` if `value` is a number, else `false`.
12008      * @example
12009      *
12010      * _.isNumber(3);
12011      * // => true
12012      *
12013      * _.isNumber(Number.MIN_VALUE);
12014      * // => true
12015      *
12016      * _.isNumber(Infinity);
12017      * // => true
12018      *
12019      * _.isNumber('3');
12020      * // => false
12021      */
12022     function isNumber(value) {
12023       return typeof value == 'number' ||
12024         (isObjectLike(value) && baseGetTag(value) == numberTag);
12025     }
12026
12027     /**
12028      * Checks if `value` is a plain object, that is, an object created by the
12029      * `Object` constructor or one with a `[[Prototype]]` of `null`.
12030      *
12031      * @static
12032      * @memberOf _
12033      * @since 0.8.0
12034      * @category Lang
12035      * @param {*} value The value to check.
12036      * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
12037      * @example
12038      *
12039      * function Foo() {
12040      *   this.a = 1;
12041      * }
12042      *
12043      * _.isPlainObject(new Foo);
12044      * // => false
12045      *
12046      * _.isPlainObject([1, 2, 3]);
12047      * // => false
12048      *
12049      * _.isPlainObject({ 'x': 0, 'y': 0 });
12050      * // => true
12051      *
12052      * _.isPlainObject(Object.create(null));
12053      * // => true
12054      */
12055     function isPlainObject(value) {
12056       if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
12057         return false;
12058       }
12059       var proto = getPrototype(value);
12060       if (proto === null) {
12061         return true;
12062       }
12063       var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
12064       return typeof Ctor == 'function' && Ctor instanceof Ctor &&
12065         funcToString.call(Ctor) == objectCtorString;
12066     }
12067
12068     /**
12069      * Checks if `value` is classified as a `RegExp` object.
12070      *
12071      * @static
12072      * @memberOf _
12073      * @since 0.1.0
12074      * @category Lang
12075      * @param {*} value The value to check.
12076      * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
12077      * @example
12078      *
12079      * _.isRegExp(/abc/);
12080      * // => true
12081      *
12082      * _.isRegExp('/abc/');
12083      * // => false
12084      */
12085     var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
12086
12087     /**
12088      * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
12089      * double precision number which isn't the result of a rounded unsafe integer.
12090      *
12091      * **Note:** This method is based on
12092      * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
12093      *
12094      * @static
12095      * @memberOf _
12096      * @since 4.0.0
12097      * @category Lang
12098      * @param {*} value The value to check.
12099      * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
12100      * @example
12101      *
12102      * _.isSafeInteger(3);
12103      * // => true
12104      *
12105      * _.isSafeInteger(Number.MIN_VALUE);
12106      * // => false
12107      *
12108      * _.isSafeInteger(Infinity);
12109      * // => false
12110      *
12111      * _.isSafeInteger('3');
12112      * // => false
12113      */
12114     function isSafeInteger(value) {
12115       return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
12116     }
12117
12118     /**
12119      * Checks if `value` is classified as a `Set` object.
12120      *
12121      * @static
12122      * @memberOf _
12123      * @since 4.3.0
12124      * @category Lang
12125      * @param {*} value The value to check.
12126      * @returns {boolean} Returns `true` if `value` is a set, else `false`.
12127      * @example
12128      *
12129      * _.isSet(new Set);
12130      * // => true
12131      *
12132      * _.isSet(new WeakSet);
12133      * // => false
12134      */
12135     var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
12136
12137     /**
12138      * Checks if `value` is classified as a `String` primitive or object.
12139      *
12140      * @static
12141      * @since 0.1.0
12142      * @memberOf _
12143      * @category Lang
12144      * @param {*} value The value to check.
12145      * @returns {boolean} Returns `true` if `value` is a string, else `false`.
12146      * @example
12147      *
12148      * _.isString('abc');
12149      * // => true
12150      *
12151      * _.isString(1);
12152      * // => false
12153      */
12154     function isString(value) {
12155       return typeof value == 'string' ||
12156         (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
12157     }
12158
12159     /**
12160      * Checks if `value` is classified as a `Symbol` primitive or object.
12161      *
12162      * @static
12163      * @memberOf _
12164      * @since 4.0.0
12165      * @category Lang
12166      * @param {*} value The value to check.
12167      * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
12168      * @example
12169      *
12170      * _.isSymbol(Symbol.iterator);
12171      * // => true
12172      *
12173      * _.isSymbol('abc');
12174      * // => false
12175      */
12176     function isSymbol(value) {
12177       return typeof value == 'symbol' ||
12178         (isObjectLike(value) && baseGetTag(value) == symbolTag);
12179     }
12180
12181     /**
12182      * Checks if `value` is classified as a typed array.
12183      *
12184      * @static
12185      * @memberOf _
12186      * @since 3.0.0
12187      * @category Lang
12188      * @param {*} value The value to check.
12189      * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
12190      * @example
12191      *
12192      * _.isTypedArray(new Uint8Array);
12193      * // => true
12194      *
12195      * _.isTypedArray([]);
12196      * // => false
12197      */
12198     var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
12199
12200     /**
12201      * Checks if `value` is `undefined`.
12202      *
12203      * @static
12204      * @since 0.1.0
12205      * @memberOf _
12206      * @category Lang
12207      * @param {*} value The value to check.
12208      * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
12209      * @example
12210      *
12211      * _.isUndefined(void 0);
12212      * // => true
12213      *
12214      * _.isUndefined(null);
12215      * // => false
12216      */
12217     function isUndefined(value) {
12218       return value === undefined;
12219     }
12220
12221     /**
12222      * Checks if `value` is classified as a `WeakMap` object.
12223      *
12224      * @static
12225      * @memberOf _
12226      * @since 4.3.0
12227      * @category Lang
12228      * @param {*} value The value to check.
12229      * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
12230      * @example
12231      *
12232      * _.isWeakMap(new WeakMap);
12233      * // => true
12234      *
12235      * _.isWeakMap(new Map);
12236      * // => false
12237      */
12238     function isWeakMap(value) {
12239       return isObjectLike(value) && getTag(value) == weakMapTag;
12240     }
12241
12242     /**
12243      * Checks if `value` is classified as a `WeakSet` object.
12244      *
12245      * @static
12246      * @memberOf _
12247      * @since 4.3.0
12248      * @category Lang
12249      * @param {*} value The value to check.
12250      * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
12251      * @example
12252      *
12253      * _.isWeakSet(new WeakSet);
12254      * // => true
12255      *
12256      * _.isWeakSet(new Set);
12257      * // => false
12258      */
12259     function isWeakSet(value) {
12260       return isObjectLike(value) && baseGetTag(value) == weakSetTag;
12261     }
12262
12263     /**
12264      * Checks if `value` is less than `other`.
12265      *
12266      * @static
12267      * @memberOf _
12268      * @since 3.9.0
12269      * @category Lang
12270      * @param {*} value The value to compare.
12271      * @param {*} other The other value to compare.
12272      * @returns {boolean} Returns `true` if `value` is less than `other`,
12273      *  else `false`.
12274      * @see _.gt
12275      * @example
12276      *
12277      * _.lt(1, 3);
12278      * // => true
12279      *
12280      * _.lt(3, 3);
12281      * // => false
12282      *
12283      * _.lt(3, 1);
12284      * // => false
12285      */
12286     var lt = createRelationalOperation(baseLt);
12287
12288     /**
12289      * Checks if `value` is less than or equal to `other`.
12290      *
12291      * @static
12292      * @memberOf _
12293      * @since 3.9.0
12294      * @category Lang
12295      * @param {*} value The value to compare.
12296      * @param {*} other The other value to compare.
12297      * @returns {boolean} Returns `true` if `value` is less than or equal to
12298      *  `other`, else `false`.
12299      * @see _.gte
12300      * @example
12301      *
12302      * _.lte(1, 3);
12303      * // => true
12304      *
12305      * _.lte(3, 3);
12306      * // => true
12307      *
12308      * _.lte(3, 1);
12309      * // => false
12310      */
12311     var lte = createRelationalOperation(function(value, other) {
12312       return value <= other;
12313     });
12314
12315     /**
12316      * Converts `value` to an array.
12317      *
12318      * @static
12319      * @since 0.1.0
12320      * @memberOf _
12321      * @category Lang
12322      * @param {*} value The value to convert.
12323      * @returns {Array} Returns the converted array.
12324      * @example
12325      *
12326      * _.toArray({ 'a': 1, 'b': 2 });
12327      * // => [1, 2]
12328      *
12329      * _.toArray('abc');
12330      * // => ['a', 'b', 'c']
12331      *
12332      * _.toArray(1);
12333      * // => []
12334      *
12335      * _.toArray(null);
12336      * // => []
12337      */
12338     function toArray(value) {
12339       if (!value) {
12340         return [];
12341       }
12342       if (isArrayLike(value)) {
12343         return isString(value) ? stringToArray(value) : copyArray(value);
12344       }
12345       if (symIterator && value[symIterator]) {
12346         return iteratorToArray(value[symIterator]());
12347       }
12348       var tag = getTag(value),
12349           func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
12350
12351       return func(value);
12352     }
12353
12354     /**
12355      * Converts `value` to a finite number.
12356      *
12357      * @static
12358      * @memberOf _
12359      * @since 4.12.0
12360      * @category Lang
12361      * @param {*} value The value to convert.
12362      * @returns {number} Returns the converted number.
12363      * @example
12364      *
12365      * _.toFinite(3.2);
12366      * // => 3.2
12367      *
12368      * _.toFinite(Number.MIN_VALUE);
12369      * // => 5e-324
12370      *
12371      * _.toFinite(Infinity);
12372      * // => 1.7976931348623157e+308
12373      *
12374      * _.toFinite('3.2');
12375      * // => 3.2
12376      */
12377     function toFinite(value) {
12378       if (!value) {
12379         return value === 0 ? value : 0;
12380       }
12381       value = toNumber(value);
12382       if (value === INFINITY || value === -INFINITY) {
12383         var sign = (value < 0 ? -1 : 1);
12384         return sign * MAX_INTEGER;
12385       }
12386       return value === value ? value : 0;
12387     }
12388
12389     /**
12390      * Converts `value` to an integer.
12391      *
12392      * **Note:** This method is loosely based on
12393      * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
12394      *
12395      * @static
12396      * @memberOf _
12397      * @since 4.0.0
12398      * @category Lang
12399      * @param {*} value The value to convert.
12400      * @returns {number} Returns the converted integer.
12401      * @example
12402      *
12403      * _.toInteger(3.2);
12404      * // => 3
12405      *
12406      * _.toInteger(Number.MIN_VALUE);
12407      * // => 0
12408      *
12409      * _.toInteger(Infinity);
12410      * // => 1.7976931348623157e+308
12411      *
12412      * _.toInteger('3.2');
12413      * // => 3
12414      */
12415     function toInteger(value) {
12416       var result = toFinite(value),
12417           remainder = result % 1;
12418
12419       return result === result ? (remainder ? result - remainder : result) : 0;
12420     }
12421
12422     /**
12423      * Converts `value` to an integer suitable for use as the length of an
12424      * array-like object.
12425      *
12426      * **Note:** This method is based on
12427      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
12428      *
12429      * @static
12430      * @memberOf _
12431      * @since 4.0.0
12432      * @category Lang
12433      * @param {*} value The value to convert.
12434      * @returns {number} Returns the converted integer.
12435      * @example
12436      *
12437      * _.toLength(3.2);
12438      * // => 3
12439      *
12440      * _.toLength(Number.MIN_VALUE);
12441      * // => 0
12442      *
12443      * _.toLength(Infinity);
12444      * // => 4294967295
12445      *
12446      * _.toLength('3.2');
12447      * // => 3
12448      */
12449     function toLength(value) {
12450       return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
12451     }
12452
12453     /**
12454      * Converts `value` to a number.
12455      *
12456      * @static
12457      * @memberOf _
12458      * @since 4.0.0
12459      * @category Lang
12460      * @param {*} value The value to process.
12461      * @returns {number} Returns the number.
12462      * @example
12463      *
12464      * _.toNumber(3.2);
12465      * // => 3.2
12466      *
12467      * _.toNumber(Number.MIN_VALUE);
12468      * // => 5e-324
12469      *
12470      * _.toNumber(Infinity);
12471      * // => Infinity
12472      *
12473      * _.toNumber('3.2');
12474      * // => 3.2
12475      */
12476     function toNumber(value) {
12477       if (typeof value == 'number') {
12478         return value;
12479       }
12480       if (isSymbol(value)) {
12481         return NAN;
12482       }
12483       if (isObject(value)) {
12484         var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
12485         value = isObject(other) ? (other + '') : other;
12486       }
12487       if (typeof value != 'string') {
12488         return value === 0 ? value : +value;
12489       }
12490       value = value.replace(reTrim, '');
12491       var isBinary = reIsBinary.test(value);
12492       return (isBinary || reIsOctal.test(value))
12493         ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
12494         : (reIsBadHex.test(value) ? NAN : +value);
12495     }
12496
12497     /**
12498      * Converts `value` to a plain object flattening inherited enumerable string
12499      * keyed properties of `value` to own properties of the plain object.
12500      *
12501      * @static
12502      * @memberOf _
12503      * @since 3.0.0
12504      * @category Lang
12505      * @param {*} value The value to convert.
12506      * @returns {Object} Returns the converted plain object.
12507      * @example
12508      *
12509      * function Foo() {
12510      *   this.b = 2;
12511      * }
12512      *
12513      * Foo.prototype.c = 3;
12514      *
12515      * _.assign({ 'a': 1 }, new Foo);
12516      * // => { 'a': 1, 'b': 2 }
12517      *
12518      * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
12519      * // => { 'a': 1, 'b': 2, 'c': 3 }
12520      */
12521     function toPlainObject(value) {
12522       return copyObject(value, keysIn(value));
12523     }
12524
12525     /**
12526      * Converts `value` to a safe integer. A safe integer can be compared and
12527      * represented correctly.
12528      *
12529      * @static
12530      * @memberOf _
12531      * @since 4.0.0
12532      * @category Lang
12533      * @param {*} value The value to convert.
12534      * @returns {number} Returns the converted integer.
12535      * @example
12536      *
12537      * _.toSafeInteger(3.2);
12538      * // => 3
12539      *
12540      * _.toSafeInteger(Number.MIN_VALUE);
12541      * // => 0
12542      *
12543      * _.toSafeInteger(Infinity);
12544      * // => 9007199254740991
12545      *
12546      * _.toSafeInteger('3.2');
12547      * // => 3
12548      */
12549     function toSafeInteger(value) {
12550       return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);
12551     }
12552
12553     /**
12554      * Converts `value` to a string. An empty string is returned for `null`
12555      * and `undefined` values. The sign of `-0` is preserved.
12556      *
12557      * @static
12558      * @memberOf _
12559      * @since 4.0.0
12560      * @category Lang
12561      * @param {*} value The value to convert.
12562      * @returns {string} Returns the converted string.
12563      * @example
12564      *
12565      * _.toString(null);
12566      * // => ''
12567      *
12568      * _.toString(-0);
12569      * // => '-0'
12570      *
12571      * _.toString([1, 2, 3]);
12572      * // => '1,2,3'
12573      */
12574     function toString(value) {
12575       return value == null ? '' : baseToString(value);
12576     }
12577
12578     /*------------------------------------------------------------------------*/
12579
12580     /**
12581      * Assigns own enumerable string keyed properties of source objects to the
12582      * destination object. Source objects are applied from left to right.
12583      * Subsequent sources overwrite property assignments of previous sources.
12584      *
12585      * **Note:** This method mutates `object` and is loosely based on
12586      * [`Object.assign`](https://mdn.io/Object/assign).
12587      *
12588      * @static
12589      * @memberOf _
12590      * @since 0.10.0
12591      * @category Object
12592      * @param {Object} object The destination object.
12593      * @param {...Object} [sources] The source objects.
12594      * @returns {Object} Returns `object`.
12595      * @see _.assignIn
12596      * @example
12597      *
12598      * function Foo() {
12599      *   this.a = 1;
12600      * }
12601      *
12602      * function Bar() {
12603      *   this.c = 3;
12604      * }
12605      *
12606      * Foo.prototype.b = 2;
12607      * Bar.prototype.d = 4;
12608      *
12609      * _.assign({ 'a': 0 }, new Foo, new Bar);
12610      * // => { 'a': 1, 'c': 3 }
12611      */
12612     var assign = createAssigner(function(object, source) {
12613       if (isPrototype(source) || isArrayLike(source)) {
12614         copyObject(source, keys(source), object);
12615         return;
12616       }
12617       for (var key in source) {
12618         if (hasOwnProperty.call(source, key)) {
12619           assignValue(object, key, source[key]);
12620         }
12621       }
12622     });
12623
12624     /**
12625      * This method is like `_.assign` except that it iterates over own and
12626      * inherited source properties.
12627      *
12628      * **Note:** This method mutates `object`.
12629      *
12630      * @static
12631      * @memberOf _
12632      * @since 4.0.0
12633      * @alias extend
12634      * @category Object
12635      * @param {Object} object The destination object.
12636      * @param {...Object} [sources] The source objects.
12637      * @returns {Object} Returns `object`.
12638      * @see _.assign
12639      * @example
12640      *
12641      * function Foo() {
12642      *   this.a = 1;
12643      * }
12644      *
12645      * function Bar() {
12646      *   this.c = 3;
12647      * }
12648      *
12649      * Foo.prototype.b = 2;
12650      * Bar.prototype.d = 4;
12651      *
12652      * _.assignIn({ 'a': 0 }, new Foo, new Bar);
12653      * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
12654      */
12655     var assignIn = createAssigner(function(object, source) {
12656       copyObject(source, keysIn(source), object);
12657     });
12658
12659     /**
12660      * This method is like `_.assignIn` except that it accepts `customizer`
12661      * which is invoked to produce the assigned values. If `customizer` returns
12662      * `undefined`, assignment is handled by the method instead. The `customizer`
12663      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12664      *
12665      * **Note:** This method mutates `object`.
12666      *
12667      * @static
12668      * @memberOf _
12669      * @since 4.0.0
12670      * @alias extendWith
12671      * @category Object
12672      * @param {Object} object The destination object.
12673      * @param {...Object} sources The source objects.
12674      * @param {Function} [customizer] The function to customize assigned values.
12675      * @returns {Object} Returns `object`.
12676      * @see _.assignWith
12677      * @example
12678      *
12679      * function customizer(objValue, srcValue) {
12680      *   return _.isUndefined(objValue) ? srcValue : objValue;
12681      * }
12682      *
12683      * var defaults = _.partialRight(_.assignInWith, customizer);
12684      *
12685      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12686      * // => { 'a': 1, 'b': 2 }
12687      */
12688     var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
12689       copyObject(source, keysIn(source), object, customizer);
12690     });
12691
12692     /**
12693      * This method is like `_.assign` except that it accepts `customizer`
12694      * which is invoked to produce the assigned values. If `customizer` returns
12695      * `undefined`, assignment is handled by the method instead. The `customizer`
12696      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12697      *
12698      * **Note:** This method mutates `object`.
12699      *
12700      * @static
12701      * @memberOf _
12702      * @since 4.0.0
12703      * @category Object
12704      * @param {Object} object The destination object.
12705      * @param {...Object} sources The source objects.
12706      * @param {Function} [customizer] The function to customize assigned values.
12707      * @returns {Object} Returns `object`.
12708      * @see _.assignInWith
12709      * @example
12710      *
12711      * function customizer(objValue, srcValue) {
12712      *   return _.isUndefined(objValue) ? srcValue : objValue;
12713      * }
12714      *
12715      * var defaults = _.partialRight(_.assignWith, customizer);
12716      *
12717      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12718      * // => { 'a': 1, 'b': 2 }
12719      */
12720     var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
12721       copyObject(source, keys(source), object, customizer);
12722     });
12723
12724     /**
12725      * Creates an array of values corresponding to `paths` of `object`.
12726      *
12727      * @static
12728      * @memberOf _
12729      * @since 1.0.0
12730      * @category Object
12731      * @param {Object} object The object to iterate over.
12732      * @param {...(string|string[])} [paths] The property paths to pick.
12733      * @returns {Array} Returns the picked values.
12734      * @example
12735      *
12736      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
12737      *
12738      * _.at(object, ['a[0].b.c', 'a[1]']);
12739      * // => [3, 4]
12740      */
12741     var at = flatRest(baseAt);
12742
12743     /**
12744      * Creates an object that inherits from the `prototype` object. If a
12745      * `properties` object is given, its own enumerable string keyed properties
12746      * are assigned to the created object.
12747      *
12748      * @static
12749      * @memberOf _
12750      * @since 2.3.0
12751      * @category Object
12752      * @param {Object} prototype The object to inherit from.
12753      * @param {Object} [properties] The properties to assign to the object.
12754      * @returns {Object} Returns the new object.
12755      * @example
12756      *
12757      * function Shape() {
12758      *   this.x = 0;
12759      *   this.y = 0;
12760      * }
12761      *
12762      * function Circle() {
12763      *   Shape.call(this);
12764      * }
12765      *
12766      * Circle.prototype = _.create(Shape.prototype, {
12767      *   'constructor': Circle
12768      * });
12769      *
12770      * var circle = new Circle;
12771      * circle instanceof Circle;
12772      * // => true
12773      *
12774      * circle instanceof Shape;
12775      * // => true
12776      */
12777     function create(prototype, properties) {
12778       var result = baseCreate(prototype);
12779       return properties == null ? result : baseAssign(result, properties);
12780     }
12781
12782     /**
12783      * Assigns own and inherited enumerable string keyed properties of source
12784      * objects to the destination object for all destination properties that
12785      * resolve to `undefined`. Source objects are applied from left to right.
12786      * Once a property is set, additional values of the same property are ignored.
12787      *
12788      * **Note:** This method mutates `object`.
12789      *
12790      * @static
12791      * @since 0.1.0
12792      * @memberOf _
12793      * @category Object
12794      * @param {Object} object The destination object.
12795      * @param {...Object} [sources] The source objects.
12796      * @returns {Object} Returns `object`.
12797      * @see _.defaultsDeep
12798      * @example
12799      *
12800      * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12801      * // => { 'a': 1, 'b': 2 }
12802      */
12803     var defaults = baseRest(function(args) {
12804       args.push(undefined, assignInDefaults);
12805       return apply(assignInWith, undefined, args);
12806     });
12807
12808     /**
12809      * This method is like `_.defaults` except that it recursively assigns
12810      * default properties.
12811      *
12812      * **Note:** This method mutates `object`.
12813      *
12814      * @static
12815      * @memberOf _
12816      * @since 3.10.0
12817      * @category Object
12818      * @param {Object} object The destination object.
12819      * @param {...Object} [sources] The source objects.
12820      * @returns {Object} Returns `object`.
12821      * @see _.defaults
12822      * @example
12823      *
12824      * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
12825      * // => { 'a': { 'b': 2, 'c': 3 } }
12826      */
12827     var defaultsDeep = baseRest(function(args) {
12828       args.push(undefined, mergeDefaults);
12829       return apply(mergeWith, undefined, args);
12830     });
12831
12832     /**
12833      * This method is like `_.find` except that it returns the key of the first
12834      * element `predicate` returns truthy for instead of the element itself.
12835      *
12836      * @static
12837      * @memberOf _
12838      * @since 1.1.0
12839      * @category Object
12840      * @param {Object} object The object to inspect.
12841      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12842      * @returns {string|undefined} Returns the key of the matched element,
12843      *  else `undefined`.
12844      * @example
12845      *
12846      * var users = {
12847      *   'barney':  { 'age': 36, 'active': true },
12848      *   'fred':    { 'age': 40, 'active': false },
12849      *   'pebbles': { 'age': 1,  'active': true }
12850      * };
12851      *
12852      * _.findKey(users, function(o) { return o.age < 40; });
12853      * // => 'barney' (iteration order is not guaranteed)
12854      *
12855      * // The `_.matches` iteratee shorthand.
12856      * _.findKey(users, { 'age': 1, 'active': true });
12857      * // => 'pebbles'
12858      *
12859      * // The `_.matchesProperty` iteratee shorthand.
12860      * _.findKey(users, ['active', false]);
12861      * // => 'fred'
12862      *
12863      * // The `_.property` iteratee shorthand.
12864      * _.findKey(users, 'active');
12865      * // => 'barney'
12866      */
12867     function findKey(object, predicate) {
12868       return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
12869     }
12870
12871     /**
12872      * This method is like `_.findKey` except that it iterates over elements of
12873      * a collection in the opposite order.
12874      *
12875      * @static
12876      * @memberOf _
12877      * @since 2.0.0
12878      * @category Object
12879      * @param {Object} object The object to inspect.
12880      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12881      * @returns {string|undefined} Returns the key of the matched element,
12882      *  else `undefined`.
12883      * @example
12884      *
12885      * var users = {
12886      *   'barney':  { 'age': 36, 'active': true },
12887      *   'fred':    { 'age': 40, 'active': false },
12888      *   'pebbles': { 'age': 1,  'active': true }
12889      * };
12890      *
12891      * _.findLastKey(users, function(o) { return o.age < 40; });
12892      * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
12893      *
12894      * // The `_.matches` iteratee shorthand.
12895      * _.findLastKey(users, { 'age': 36, 'active': true });
12896      * // => 'barney'
12897      *
12898      * // The `_.matchesProperty` iteratee shorthand.
12899      * _.findLastKey(users, ['active', false]);
12900      * // => 'fred'
12901      *
12902      * // The `_.property` iteratee shorthand.
12903      * _.findLastKey(users, 'active');
12904      * // => 'pebbles'
12905      */
12906     function findLastKey(object, predicate) {
12907       return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
12908     }
12909
12910     /**
12911      * Iterates over own and inherited enumerable string keyed properties of an
12912      * object and invokes `iteratee` for each property. The iteratee is invoked
12913      * with three arguments: (value, key, object). Iteratee functions may exit
12914      * iteration early by explicitly returning `false`.
12915      *
12916      * @static
12917      * @memberOf _
12918      * @since 0.3.0
12919      * @category Object
12920      * @param {Object} object The object to iterate over.
12921      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12922      * @returns {Object} Returns `object`.
12923      * @see _.forInRight
12924      * @example
12925      *
12926      * function Foo() {
12927      *   this.a = 1;
12928      *   this.b = 2;
12929      * }
12930      *
12931      * Foo.prototype.c = 3;
12932      *
12933      * _.forIn(new Foo, function(value, key) {
12934      *   console.log(key);
12935      * });
12936      * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
12937      */
12938     function forIn(object, iteratee) {
12939       return object == null
12940         ? object
12941         : baseFor(object, getIteratee(iteratee, 3), keysIn);
12942     }
12943
12944     /**
12945      * This method is like `_.forIn` except that it iterates over properties of
12946      * `object` in the opposite order.
12947      *
12948      * @static
12949      * @memberOf _
12950      * @since 2.0.0
12951      * @category Object
12952      * @param {Object} object The object to iterate over.
12953      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12954      * @returns {Object} Returns `object`.
12955      * @see _.forIn
12956      * @example
12957      *
12958      * function Foo() {
12959      *   this.a = 1;
12960      *   this.b = 2;
12961      * }
12962      *
12963      * Foo.prototype.c = 3;
12964      *
12965      * _.forInRight(new Foo, function(value, key) {
12966      *   console.log(key);
12967      * });
12968      * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
12969      */
12970     function forInRight(object, iteratee) {
12971       return object == null
12972         ? object
12973         : baseForRight(object, getIteratee(iteratee, 3), keysIn);
12974     }
12975
12976     /**
12977      * Iterates over own enumerable string keyed properties of an object and
12978      * invokes `iteratee` for each property. The iteratee is invoked with three
12979      * arguments: (value, key, object). Iteratee functions may exit iteration
12980      * early by explicitly returning `false`.
12981      *
12982      * @static
12983      * @memberOf _
12984      * @since 0.3.0
12985      * @category Object
12986      * @param {Object} object The object to iterate over.
12987      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12988      * @returns {Object} Returns `object`.
12989      * @see _.forOwnRight
12990      * @example
12991      *
12992      * function Foo() {
12993      *   this.a = 1;
12994      *   this.b = 2;
12995      * }
12996      *
12997      * Foo.prototype.c = 3;
12998      *
12999      * _.forOwn(new Foo, function(value, key) {
13000      *   console.log(key);
13001      * });
13002      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
13003      */
13004     function forOwn(object, iteratee) {
13005       return object && baseForOwn(object, getIteratee(iteratee, 3));
13006     }
13007
13008     /**
13009      * This method is like `_.forOwn` except that it iterates over properties of
13010      * `object` in the opposite order.
13011      *
13012      * @static
13013      * @memberOf _
13014      * @since 2.0.0
13015      * @category Object
13016      * @param {Object} object The object to iterate over.
13017      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13018      * @returns {Object} Returns `object`.
13019      * @see _.forOwn
13020      * @example
13021      *
13022      * function Foo() {
13023      *   this.a = 1;
13024      *   this.b = 2;
13025      * }
13026      *
13027      * Foo.prototype.c = 3;
13028      *
13029      * _.forOwnRight(new Foo, function(value, key) {
13030      *   console.log(key);
13031      * });
13032      * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
13033      */
13034     function forOwnRight(object, iteratee) {
13035       return object && baseForOwnRight(object, getIteratee(iteratee, 3));
13036     }
13037
13038     /**
13039      * Creates an array of function property names from own enumerable properties
13040      * of `object`.
13041      *
13042      * @static
13043      * @since 0.1.0
13044      * @memberOf _
13045      * @category Object
13046      * @param {Object} object The object to inspect.
13047      * @returns {Array} Returns the function names.
13048      * @see _.functionsIn
13049      * @example
13050      *
13051      * function Foo() {
13052      *   this.a = _.constant('a');
13053      *   this.b = _.constant('b');
13054      * }
13055      *
13056      * Foo.prototype.c = _.constant('c');
13057      *
13058      * _.functions(new Foo);
13059      * // => ['a', 'b']
13060      */
13061     function functions(object) {
13062       return object == null ? [] : baseFunctions(object, keys(object));
13063     }
13064
13065     /**
13066      * Creates an array of function property names from own and inherited
13067      * enumerable properties of `object`.
13068      *
13069      * @static
13070      * @memberOf _
13071      * @since 4.0.0
13072      * @category Object
13073      * @param {Object} object The object to inspect.
13074      * @returns {Array} Returns the function names.
13075      * @see _.functions
13076      * @example
13077      *
13078      * function Foo() {
13079      *   this.a = _.constant('a');
13080      *   this.b = _.constant('b');
13081      * }
13082      *
13083      * Foo.prototype.c = _.constant('c');
13084      *
13085      * _.functionsIn(new Foo);
13086      * // => ['a', 'b', 'c']
13087      */
13088     function functionsIn(object) {
13089       return object == null ? [] : baseFunctions(object, keysIn(object));
13090     }
13091
13092     /**
13093      * Gets the value at `path` of `object`. If the resolved value is
13094      * `undefined`, the `defaultValue` is returned in its place.
13095      *
13096      * @static
13097      * @memberOf _
13098      * @since 3.7.0
13099      * @category Object
13100      * @param {Object} object The object to query.
13101      * @param {Array|string} path The path of the property to get.
13102      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13103      * @returns {*} Returns the resolved value.
13104      * @example
13105      *
13106      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13107      *
13108      * _.get(object, 'a[0].b.c');
13109      * // => 3
13110      *
13111      * _.get(object, ['a', '0', 'b', 'c']);
13112      * // => 3
13113      *
13114      * _.get(object, 'a.b.c', 'default');
13115      * // => 'default'
13116      */
13117     function get(object, path, defaultValue) {
13118       var result = object == null ? undefined : baseGet(object, path);
13119       return result === undefined ? defaultValue : result;
13120     }
13121
13122     /**
13123      * Checks if `path` is a direct property of `object`.
13124      *
13125      * @static
13126      * @since 0.1.0
13127      * @memberOf _
13128      * @category Object
13129      * @param {Object} object The object to query.
13130      * @param {Array|string} path The path to check.
13131      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13132      * @example
13133      *
13134      * var object = { 'a': { 'b': 2 } };
13135      * var other = _.create({ 'a': _.create({ 'b': 2 }) });
13136      *
13137      * _.has(object, 'a');
13138      * // => true
13139      *
13140      * _.has(object, 'a.b');
13141      * // => true
13142      *
13143      * _.has(object, ['a', 'b']);
13144      * // => true
13145      *
13146      * _.has(other, 'a');
13147      * // => false
13148      */
13149     function has(object, path) {
13150       return object != null && hasPath(object, path, baseHas);
13151     }
13152
13153     /**
13154      * Checks if `path` is a direct or inherited property of `object`.
13155      *
13156      * @static
13157      * @memberOf _
13158      * @since 4.0.0
13159      * @category Object
13160      * @param {Object} object The object to query.
13161      * @param {Array|string} path The path to check.
13162      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13163      * @example
13164      *
13165      * var object = _.create({ 'a': _.create({ 'b': 2 }) });
13166      *
13167      * _.hasIn(object, 'a');
13168      * // => true
13169      *
13170      * _.hasIn(object, 'a.b');
13171      * // => true
13172      *
13173      * _.hasIn(object, ['a', 'b']);
13174      * // => true
13175      *
13176      * _.hasIn(object, 'b');
13177      * // => false
13178      */
13179     function hasIn(object, path) {
13180       return object != null && hasPath(object, path, baseHasIn);
13181     }
13182
13183     /**
13184      * Creates an object composed of the inverted keys and values of `object`.
13185      * If `object` contains duplicate values, subsequent values overwrite
13186      * property assignments of previous values.
13187      *
13188      * @static
13189      * @memberOf _
13190      * @since 0.7.0
13191      * @category Object
13192      * @param {Object} object The object to invert.
13193      * @returns {Object} Returns the new inverted object.
13194      * @example
13195      *
13196      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13197      *
13198      * _.invert(object);
13199      * // => { '1': 'c', '2': 'b' }
13200      */
13201     var invert = createInverter(function(result, value, key) {
13202       result[value] = key;
13203     }, constant(identity));
13204
13205     /**
13206      * This method is like `_.invert` except that the inverted object is generated
13207      * from the results of running each element of `object` thru `iteratee`. The
13208      * corresponding inverted value of each inverted key is an array of keys
13209      * responsible for generating the inverted value. The iteratee is invoked
13210      * with one argument: (value).
13211      *
13212      * @static
13213      * @memberOf _
13214      * @since 4.1.0
13215      * @category Object
13216      * @param {Object} object The object to invert.
13217      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
13218      * @returns {Object} Returns the new inverted object.
13219      * @example
13220      *
13221      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13222      *
13223      * _.invertBy(object);
13224      * // => { '1': ['a', 'c'], '2': ['b'] }
13225      *
13226      * _.invertBy(object, function(value) {
13227      *   return 'group' + value;
13228      * });
13229      * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
13230      */
13231     var invertBy = createInverter(function(result, value, key) {
13232       if (hasOwnProperty.call(result, value)) {
13233         result[value].push(key);
13234       } else {
13235         result[value] = [key];
13236       }
13237     }, getIteratee);
13238
13239     /**
13240      * Invokes the method at `path` of `object`.
13241      *
13242      * @static
13243      * @memberOf _
13244      * @since 4.0.0
13245      * @category Object
13246      * @param {Object} object The object to query.
13247      * @param {Array|string} path The path of the method to invoke.
13248      * @param {...*} [args] The arguments to invoke the method with.
13249      * @returns {*} Returns the result of the invoked method.
13250      * @example
13251      *
13252      * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
13253      *
13254      * _.invoke(object, 'a[0].b.c.slice', 1, 3);
13255      * // => [2, 3]
13256      */
13257     var invoke = baseRest(baseInvoke);
13258
13259     /**
13260      * Creates an array of the own enumerable property names of `object`.
13261      *
13262      * **Note:** Non-object values are coerced to objects. See the
13263      * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
13264      * for more details.
13265      *
13266      * @static
13267      * @since 0.1.0
13268      * @memberOf _
13269      * @category Object
13270      * @param {Object} object The object to query.
13271      * @returns {Array} Returns the array of property names.
13272      * @example
13273      *
13274      * function Foo() {
13275      *   this.a = 1;
13276      *   this.b = 2;
13277      * }
13278      *
13279      * Foo.prototype.c = 3;
13280      *
13281      * _.keys(new Foo);
13282      * // => ['a', 'b'] (iteration order is not guaranteed)
13283      *
13284      * _.keys('hi');
13285      * // => ['0', '1']
13286      */
13287     function keys(object) {
13288       return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
13289     }
13290
13291     /**
13292      * Creates an array of the own and inherited enumerable property names of `object`.
13293      *
13294      * **Note:** Non-object values are coerced to objects.
13295      *
13296      * @static
13297      * @memberOf _
13298      * @since 3.0.0
13299      * @category Object
13300      * @param {Object} object The object to query.
13301      * @returns {Array} Returns the array of property names.
13302      * @example
13303      *
13304      * function Foo() {
13305      *   this.a = 1;
13306      *   this.b = 2;
13307      * }
13308      *
13309      * Foo.prototype.c = 3;
13310      *
13311      * _.keysIn(new Foo);
13312      * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
13313      */
13314     function keysIn(object) {
13315       return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
13316     }
13317
13318     /**
13319      * The opposite of `_.mapValues`; this method creates an object with the
13320      * same values as `object` and keys generated by running each own enumerable
13321      * string keyed property of `object` thru `iteratee`. The iteratee is invoked
13322      * with three arguments: (value, key, object).
13323      *
13324      * @static
13325      * @memberOf _
13326      * @since 3.8.0
13327      * @category Object
13328      * @param {Object} object The object to iterate over.
13329      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13330      * @returns {Object} Returns the new mapped object.
13331      * @see _.mapValues
13332      * @example
13333      *
13334      * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
13335      *   return key + value;
13336      * });
13337      * // => { 'a1': 1, 'b2': 2 }
13338      */
13339     function mapKeys(object, iteratee) {
13340       var result = {};
13341       iteratee = getIteratee(iteratee, 3);
13342
13343       baseForOwn(object, function(value, key, object) {
13344         baseAssignValue(result, iteratee(value, key, object), value);
13345       });
13346       return result;
13347     }
13348
13349     /**
13350      * Creates an object with the same keys as `object` and values generated
13351      * by running each own enumerable string keyed property of `object` thru
13352      * `iteratee`. The iteratee is invoked with three arguments:
13353      * (value, key, object).
13354      *
13355      * @static
13356      * @memberOf _
13357      * @since 2.4.0
13358      * @category Object
13359      * @param {Object} object The object to iterate over.
13360      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13361      * @returns {Object} Returns the new mapped object.
13362      * @see _.mapKeys
13363      * @example
13364      *
13365      * var users = {
13366      *   'fred':    { 'user': 'fred',    'age': 40 },
13367      *   'pebbles': { 'user': 'pebbles', 'age': 1 }
13368      * };
13369      *
13370      * _.mapValues(users, function(o) { return o.age; });
13371      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13372      *
13373      * // The `_.property` iteratee shorthand.
13374      * _.mapValues(users, 'age');
13375      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13376      */
13377     function mapValues(object, iteratee) {
13378       var result = {};
13379       iteratee = getIteratee(iteratee, 3);
13380
13381       baseForOwn(object, function(value, key, object) {
13382         baseAssignValue(result, key, iteratee(value, key, object));
13383       });
13384       return result;
13385     }
13386
13387     /**
13388      * This method is like `_.assign` except that it recursively merges own and
13389      * inherited enumerable string keyed properties of source objects into the
13390      * destination object. Source properties that resolve to `undefined` are
13391      * skipped if a destination value exists. Array and plain object properties
13392      * are merged recursively. Other objects and value types are overridden by
13393      * assignment. Source objects are applied from left to right. Subsequent
13394      * sources overwrite property assignments of previous sources.
13395      *
13396      * **Note:** This method mutates `object`.
13397      *
13398      * @static
13399      * @memberOf _
13400      * @since 0.5.0
13401      * @category Object
13402      * @param {Object} object The destination object.
13403      * @param {...Object} [sources] The source objects.
13404      * @returns {Object} Returns `object`.
13405      * @example
13406      *
13407      * var object = {
13408      *   'a': [{ 'b': 2 }, { 'd': 4 }]
13409      * };
13410      *
13411      * var other = {
13412      *   'a': [{ 'c': 3 }, { 'e': 5 }]
13413      * };
13414      *
13415      * _.merge(object, other);
13416      * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
13417      */
13418     var merge = createAssigner(function(object, source, srcIndex) {
13419       baseMerge(object, source, srcIndex);
13420     });
13421
13422     /**
13423      * This method is like `_.merge` except that it accepts `customizer` which
13424      * is invoked to produce the merged values of the destination and source
13425      * properties. If `customizer` returns `undefined`, merging is handled by the
13426      * method instead. The `customizer` is invoked with six arguments:
13427      * (objValue, srcValue, key, object, source, stack).
13428      *
13429      * **Note:** This method mutates `object`.
13430      *
13431      * @static
13432      * @memberOf _
13433      * @since 4.0.0
13434      * @category Object
13435      * @param {Object} object The destination object.
13436      * @param {...Object} sources The source objects.
13437      * @param {Function} customizer The function to customize assigned values.
13438      * @returns {Object} Returns `object`.
13439      * @example
13440      *
13441      * function customizer(objValue, srcValue) {
13442      *   if (_.isArray(objValue)) {
13443      *     return objValue.concat(srcValue);
13444      *   }
13445      * }
13446      *
13447      * var object = { 'a': [1], 'b': [2] };
13448      * var other = { 'a': [3], 'b': [4] };
13449      *
13450      * _.mergeWith(object, other, customizer);
13451      * // => { 'a': [1, 3], 'b': [2, 4] }
13452      */
13453     var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
13454       baseMerge(object, source, srcIndex, customizer);
13455     });
13456
13457     /**
13458      * The opposite of `_.pick`; this method creates an object composed of the
13459      * own and inherited enumerable property paths of `object` that are not omitted.
13460      *
13461      * **Note:** This method is considerably slower than `_.pick`.
13462      *
13463      * @static
13464      * @since 0.1.0
13465      * @memberOf _
13466      * @category Object
13467      * @param {Object} object The source object.
13468      * @param {...(string|string[])} [paths] The property paths to omit.
13469      * @returns {Object} Returns the new object.
13470      * @example
13471      *
13472      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13473      *
13474      * _.omit(object, ['a', 'c']);
13475      * // => { 'b': '2' }
13476      */
13477     var omit = flatRest(function(object, paths) {
13478       var result = {};
13479       if (object == null) {
13480         return result;
13481       }
13482       var isDeep = false;
13483       paths = arrayMap(paths, function(path) {
13484         path = castPath(path, object);
13485         isDeep || (isDeep = path.length > 1);
13486         return path;
13487       });
13488       copyObject(object, getAllKeysIn(object), result);
13489       if (isDeep) {
13490         result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG);
13491       }
13492       var length = paths.length;
13493       while (length--) {
13494         baseUnset(result, paths[length]);
13495       }
13496       return result;
13497     });
13498
13499     /**
13500      * The opposite of `_.pickBy`; this method creates an object composed of
13501      * the own and inherited enumerable string keyed properties of `object` that
13502      * `predicate` doesn't return truthy for. The predicate is invoked with two
13503      * arguments: (value, key).
13504      *
13505      * @static
13506      * @memberOf _
13507      * @since 4.0.0
13508      * @category Object
13509      * @param {Object} object The source object.
13510      * @param {Function} [predicate=_.identity] The function invoked per property.
13511      * @returns {Object} Returns the new object.
13512      * @example
13513      *
13514      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13515      *
13516      * _.omitBy(object, _.isNumber);
13517      * // => { 'b': '2' }
13518      */
13519     function omitBy(object, predicate) {
13520       return pickBy(object, negate(getIteratee(predicate)));
13521     }
13522
13523     /**
13524      * Creates an object composed of the picked `object` properties.
13525      *
13526      * @static
13527      * @since 0.1.0
13528      * @memberOf _
13529      * @category Object
13530      * @param {Object} object The source object.
13531      * @param {...(string|string[])} [paths] The property paths to pick.
13532      * @returns {Object} Returns the new object.
13533      * @example
13534      *
13535      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13536      *
13537      * _.pick(object, ['a', 'c']);
13538      * // => { 'a': 1, 'c': 3 }
13539      */
13540     var pick = flatRest(function(object, paths) {
13541       return object == null ? {} : basePick(object, paths);
13542     });
13543
13544     /**
13545      * Creates an object composed of the `object` properties `predicate` returns
13546      * truthy for. The predicate is invoked with two arguments: (value, key).
13547      *
13548      * @static
13549      * @memberOf _
13550      * @since 4.0.0
13551      * @category Object
13552      * @param {Object} object The source object.
13553      * @param {Function} [predicate=_.identity] The function invoked per property.
13554      * @returns {Object} Returns the new object.
13555      * @example
13556      *
13557      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13558      *
13559      * _.pickBy(object, _.isNumber);
13560      * // => { 'a': 1, 'c': 3 }
13561      */
13562     function pickBy(object, predicate) {
13563       if (object == null) {
13564         return {};
13565       }
13566       var props = arrayMap(getAllKeysIn(object), function(prop) {
13567         return [prop];
13568       });
13569       predicate = getIteratee(predicate);
13570       return basePickBy(object, props, function(value, path) {
13571         return predicate(value, path[0]);
13572       });
13573     }
13574
13575     /**
13576      * This method is like `_.get` except that if the resolved value is a
13577      * function it's invoked with the `this` binding of its parent object and
13578      * its result is returned.
13579      *
13580      * @static
13581      * @since 0.1.0
13582      * @memberOf _
13583      * @category Object
13584      * @param {Object} object The object to query.
13585      * @param {Array|string} path The path of the property to resolve.
13586      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13587      * @returns {*} Returns the resolved value.
13588      * @example
13589      *
13590      * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
13591      *
13592      * _.result(object, 'a[0].b.c1');
13593      * // => 3
13594      *
13595      * _.result(object, 'a[0].b.c2');
13596      * // => 4
13597      *
13598      * _.result(object, 'a[0].b.c3', 'default');
13599      * // => 'default'
13600      *
13601      * _.result(object, 'a[0].b.c3', _.constant('default'));
13602      * // => 'default'
13603      */
13604     function result(object, path, defaultValue) {
13605       path = castPath(path, object);
13606
13607       var index = -1,
13608           length = path.length;
13609
13610       // Ensure the loop is entered when path is empty.
13611       if (!length) {
13612         length = 1;
13613         object = undefined;
13614       }
13615       while (++index < length) {
13616         var value = object == null ? undefined : object[toKey(path[index])];
13617         if (value === undefined) {
13618           index = length;
13619           value = defaultValue;
13620         }
13621         object = isFunction(value) ? value.call(object) : value;
13622       }
13623       return object;
13624     }
13625
13626     /**
13627      * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
13628      * it's created. Arrays are created for missing index properties while objects
13629      * are created for all other missing properties. Use `_.setWith` to customize
13630      * `path` creation.
13631      *
13632      * **Note:** This method mutates `object`.
13633      *
13634      * @static
13635      * @memberOf _
13636      * @since 3.7.0
13637      * @category Object
13638      * @param {Object} object The object to modify.
13639      * @param {Array|string} path The path of the property to set.
13640      * @param {*} value The value to set.
13641      * @returns {Object} Returns `object`.
13642      * @example
13643      *
13644      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13645      *
13646      * _.set(object, 'a[0].b.c', 4);
13647      * console.log(object.a[0].b.c);
13648      * // => 4
13649      *
13650      * _.set(object, ['x', '0', 'y', 'z'], 5);
13651      * console.log(object.x[0].y.z);
13652      * // => 5
13653      */
13654     function set(object, path, value) {
13655       return object == null ? object : baseSet(object, path, value);
13656     }
13657
13658     /**
13659      * This method is like `_.set` except that it accepts `customizer` which is
13660      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13661      * path creation is handled by the method instead. The `customizer` is invoked
13662      * with three arguments: (nsValue, key, nsObject).
13663      *
13664      * **Note:** This method mutates `object`.
13665      *
13666      * @static
13667      * @memberOf _
13668      * @since 4.0.0
13669      * @category Object
13670      * @param {Object} object The object to modify.
13671      * @param {Array|string} path The path of the property to set.
13672      * @param {*} value The value to set.
13673      * @param {Function} [customizer] The function to customize assigned values.
13674      * @returns {Object} Returns `object`.
13675      * @example
13676      *
13677      * var object = {};
13678      *
13679      * _.setWith(object, '[0][1]', 'a', Object);
13680      * // => { '0': { '1': 'a' } }
13681      */
13682     function setWith(object, path, value, customizer) {
13683       customizer = typeof customizer == 'function' ? customizer : undefined;
13684       return object == null ? object : baseSet(object, path, value, customizer);
13685     }
13686
13687     /**
13688      * Creates an array of own enumerable string keyed-value pairs for `object`
13689      * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
13690      * entries are returned.
13691      *
13692      * @static
13693      * @memberOf _
13694      * @since 4.0.0
13695      * @alias entries
13696      * @category Object
13697      * @param {Object} object The object to query.
13698      * @returns {Array} Returns the key-value pairs.
13699      * @example
13700      *
13701      * function Foo() {
13702      *   this.a = 1;
13703      *   this.b = 2;
13704      * }
13705      *
13706      * Foo.prototype.c = 3;
13707      *
13708      * _.toPairs(new Foo);
13709      * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
13710      */
13711     var toPairs = createToPairs(keys);
13712
13713     /**
13714      * Creates an array of own and inherited enumerable string keyed-value pairs
13715      * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
13716      * or set, its entries are returned.
13717      *
13718      * @static
13719      * @memberOf _
13720      * @since 4.0.0
13721      * @alias entriesIn
13722      * @category Object
13723      * @param {Object} object The object to query.
13724      * @returns {Array} Returns the key-value pairs.
13725      * @example
13726      *
13727      * function Foo() {
13728      *   this.a = 1;
13729      *   this.b = 2;
13730      * }
13731      *
13732      * Foo.prototype.c = 3;
13733      *
13734      * _.toPairsIn(new Foo);
13735      * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
13736      */
13737     var toPairsIn = createToPairs(keysIn);
13738
13739     /**
13740      * An alternative to `_.reduce`; this method transforms `object` to a new
13741      * `accumulator` object which is the result of running each of its own
13742      * enumerable string keyed properties thru `iteratee`, with each invocation
13743      * potentially mutating the `accumulator` object. If `accumulator` is not
13744      * provided, a new object with the same `[[Prototype]]` will be used. The
13745      * iteratee is invoked with four arguments: (accumulator, value, key, object).
13746      * Iteratee functions may exit iteration early by explicitly returning `false`.
13747      *
13748      * @static
13749      * @memberOf _
13750      * @since 1.3.0
13751      * @category Object
13752      * @param {Object} object The object to iterate over.
13753      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13754      * @param {*} [accumulator] The custom accumulator value.
13755      * @returns {*} Returns the accumulated value.
13756      * @example
13757      *
13758      * _.transform([2, 3, 4], function(result, n) {
13759      *   result.push(n *= n);
13760      *   return n % 2 == 0;
13761      * }, []);
13762      * // => [4, 9]
13763      *
13764      * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
13765      *   (result[value] || (result[value] = [])).push(key);
13766      * }, {});
13767      * // => { '1': ['a', 'c'], '2': ['b'] }
13768      */
13769     function transform(object, iteratee, accumulator) {
13770       var isArr = isArray(object),
13771           isArrLike = isArr || isBuffer(object) || isTypedArray(object);
13772
13773       iteratee = getIteratee(iteratee, 4);
13774       if (accumulator == null) {
13775         var Ctor = object && object.constructor;
13776         if (isArrLike) {
13777           accumulator = isArr ? new Ctor : [];
13778         }
13779         else if (isObject(object)) {
13780           accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
13781         }
13782         else {
13783           accumulator = {};
13784         }
13785       }
13786       (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
13787         return iteratee(accumulator, value, index, object);
13788       });
13789       return accumulator;
13790     }
13791
13792     /**
13793      * Removes the property at `path` of `object`.
13794      *
13795      * **Note:** This method mutates `object`.
13796      *
13797      * @static
13798      * @memberOf _
13799      * @since 4.0.0
13800      * @category Object
13801      * @param {Object} object The object to modify.
13802      * @param {Array|string} path The path of the property to unset.
13803      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
13804      * @example
13805      *
13806      * var object = { 'a': [{ 'b': { 'c': 7 } }] };
13807      * _.unset(object, 'a[0].b.c');
13808      * // => true
13809      *
13810      * console.log(object);
13811      * // => { 'a': [{ 'b': {} }] };
13812      *
13813      * _.unset(object, ['a', '0', 'b', 'c']);
13814      * // => true
13815      *
13816      * console.log(object);
13817      * // => { 'a': [{ 'b': {} }] };
13818      */
13819     function unset(object, path) {
13820       return object == null ? true : baseUnset(object, path);
13821     }
13822
13823     /**
13824      * This method is like `_.set` except that accepts `updater` to produce the
13825      * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
13826      * is invoked with one argument: (value).
13827      *
13828      * **Note:** This method mutates `object`.
13829      *
13830      * @static
13831      * @memberOf _
13832      * @since 4.6.0
13833      * @category Object
13834      * @param {Object} object The object to modify.
13835      * @param {Array|string} path The path of the property to set.
13836      * @param {Function} updater The function to produce the updated value.
13837      * @returns {Object} Returns `object`.
13838      * @example
13839      *
13840      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13841      *
13842      * _.update(object, 'a[0].b.c', function(n) { return n * n; });
13843      * console.log(object.a[0].b.c);
13844      * // => 9
13845      *
13846      * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
13847      * console.log(object.x[0].y.z);
13848      * // => 0
13849      */
13850     function update(object, path, updater) {
13851       return object == null ? object : baseUpdate(object, path, castFunction(updater));
13852     }
13853
13854     /**
13855      * This method is like `_.update` except that it accepts `customizer` which is
13856      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13857      * path creation is handled by the method instead. The `customizer` is invoked
13858      * with three arguments: (nsValue, key, nsObject).
13859      *
13860      * **Note:** This method mutates `object`.
13861      *
13862      * @static
13863      * @memberOf _
13864      * @since 4.6.0
13865      * @category Object
13866      * @param {Object} object The object to modify.
13867      * @param {Array|string} path The path of the property to set.
13868      * @param {Function} updater The function to produce the updated value.
13869      * @param {Function} [customizer] The function to customize assigned values.
13870      * @returns {Object} Returns `object`.
13871      * @example
13872      *
13873      * var object = {};
13874      *
13875      * _.updateWith(object, '[0][1]', _.constant('a'), Object);
13876      * // => { '0': { '1': 'a' } }
13877      */
13878     function updateWith(object, path, updater, customizer) {
13879       customizer = typeof customizer == 'function' ? customizer : undefined;
13880       return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
13881     }
13882
13883     /**
13884      * Creates an array of the own enumerable string keyed property values of `object`.
13885      *
13886      * **Note:** Non-object values are coerced to objects.
13887      *
13888      * @static
13889      * @since 0.1.0
13890      * @memberOf _
13891      * @category Object
13892      * @param {Object} object The object to query.
13893      * @returns {Array} Returns the array of property values.
13894      * @example
13895      *
13896      * function Foo() {
13897      *   this.a = 1;
13898      *   this.b = 2;
13899      * }
13900      *
13901      * Foo.prototype.c = 3;
13902      *
13903      * _.values(new Foo);
13904      * // => [1, 2] (iteration order is not guaranteed)
13905      *
13906      * _.values('hi');
13907      * // => ['h', 'i']
13908      */
13909     function values(object) {
13910       return object == null ? [] : baseValues(object, keys(object));
13911     }
13912
13913     /**
13914      * Creates an array of the own and inherited enumerable string keyed property
13915      * values of `object`.
13916      *
13917      * **Note:** Non-object values are coerced to objects.
13918      *
13919      * @static
13920      * @memberOf _
13921      * @since 3.0.0
13922      * @category Object
13923      * @param {Object} object The object to query.
13924      * @returns {Array} Returns the array of property values.
13925      * @example
13926      *
13927      * function Foo() {
13928      *   this.a = 1;
13929      *   this.b = 2;
13930      * }
13931      *
13932      * Foo.prototype.c = 3;
13933      *
13934      * _.valuesIn(new Foo);
13935      * // => [1, 2, 3] (iteration order is not guaranteed)
13936      */
13937     function valuesIn(object) {
13938       return object == null ? [] : baseValues(object, keysIn(object));
13939     }
13940
13941     /*------------------------------------------------------------------------*/
13942
13943     /**
13944      * Clamps `number` within the inclusive `lower` and `upper` bounds.
13945      *
13946      * @static
13947      * @memberOf _
13948      * @since 4.0.0
13949      * @category Number
13950      * @param {number} number The number to clamp.
13951      * @param {number} [lower] The lower bound.
13952      * @param {number} upper The upper bound.
13953      * @returns {number} Returns the clamped number.
13954      * @example
13955      *
13956      * _.clamp(-10, -5, 5);
13957      * // => -5
13958      *
13959      * _.clamp(10, -5, 5);
13960      * // => 5
13961      */
13962     function clamp(number, lower, upper) {
13963       if (upper === undefined) {
13964         upper = lower;
13965         lower = undefined;
13966       }
13967       if (upper !== undefined) {
13968         upper = toNumber(upper);
13969         upper = upper === upper ? upper : 0;
13970       }
13971       if (lower !== undefined) {
13972         lower = toNumber(lower);
13973         lower = lower === lower ? lower : 0;
13974       }
13975       return baseClamp(toNumber(number), lower, upper);
13976     }
13977
13978     /**
13979      * Checks if `n` is between `start` and up to, but not including, `end`. If
13980      * `end` is not specified, it's set to `start` with `start` then set to `0`.
13981      * If `start` is greater than `end` the params are swapped to support
13982      * negative ranges.
13983      *
13984      * @static
13985      * @memberOf _
13986      * @since 3.3.0
13987      * @category Number
13988      * @param {number} number The number to check.
13989      * @param {number} [start=0] The start of the range.
13990      * @param {number} end The end of the range.
13991      * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
13992      * @see _.range, _.rangeRight
13993      * @example
13994      *
13995      * _.inRange(3, 2, 4);
13996      * // => true
13997      *
13998      * _.inRange(4, 8);
13999      * // => true
14000      *
14001      * _.inRange(4, 2);
14002      * // => false
14003      *
14004      * _.inRange(2, 2);
14005      * // => false
14006      *
14007      * _.inRange(1.2, 2);
14008      * // => true
14009      *
14010      * _.inRange(5.2, 4);
14011      * // => false
14012      *
14013      * _.inRange(-3, -2, -6);
14014      * // => true
14015      */
14016     function inRange(number, start, end) {
14017       start = toFinite(start);
14018       if (end === undefined) {
14019         end = start;
14020         start = 0;
14021       } else {
14022         end = toFinite(end);
14023       }
14024       number = toNumber(number);
14025       return baseInRange(number, start, end);
14026     }
14027
14028     /**
14029      * Produces a random number between the inclusive `lower` and `upper` bounds.
14030      * If only one argument is provided a number between `0` and the given number
14031      * is returned. If `floating` is `true`, or either `lower` or `upper` are
14032      * floats, a floating-point number is returned instead of an integer.
14033      *
14034      * **Note:** JavaScript follows the IEEE-754 standard for resolving
14035      * floating-point values which can produce unexpected results.
14036      *
14037      * @static
14038      * @memberOf _
14039      * @since 0.7.0
14040      * @category Number
14041      * @param {number} [lower=0] The lower bound.
14042      * @param {number} [upper=1] The upper bound.
14043      * @param {boolean} [floating] Specify returning a floating-point number.
14044      * @returns {number} Returns the random number.
14045      * @example
14046      *
14047      * _.random(0, 5);
14048      * // => an integer between 0 and 5
14049      *
14050      * _.random(5);
14051      * // => also an integer between 0 and 5
14052      *
14053      * _.random(5, true);
14054      * // => a floating-point number between 0 and 5
14055      *
14056      * _.random(1.2, 5.2);
14057      * // => a floating-point number between 1.2 and 5.2
14058      */
14059     function random(lower, upper, floating) {
14060       if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
14061         upper = floating = undefined;
14062       }
14063       if (floating === undefined) {
14064         if (typeof upper == 'boolean') {
14065           floating = upper;
14066           upper = undefined;
14067         }
14068         else if (typeof lower == 'boolean') {
14069           floating = lower;
14070           lower = undefined;
14071         }
14072       }
14073       if (lower === undefined && upper === undefined) {
14074         lower = 0;
14075         upper = 1;
14076       }
14077       else {
14078         lower = toFinite(lower);
14079         if (upper === undefined) {
14080           upper = lower;
14081           lower = 0;
14082         } else {
14083           upper = toFinite(upper);
14084         }
14085       }
14086       if (lower > upper) {
14087         var temp = lower;
14088         lower = upper;
14089         upper = temp;
14090       }
14091       if (floating || lower % 1 || upper % 1) {
14092         var rand = nativeRandom();
14093         return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
14094       }
14095       return baseRandom(lower, upper);
14096     }
14097
14098     /*------------------------------------------------------------------------*/
14099
14100     /**
14101      * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
14102      *
14103      * @static
14104      * @memberOf _
14105      * @since 3.0.0
14106      * @category String
14107      * @param {string} [string=''] The string to convert.
14108      * @returns {string} Returns the camel cased string.
14109      * @example
14110      *
14111      * _.camelCase('Foo Bar');
14112      * // => 'fooBar'
14113      *
14114      * _.camelCase('--foo-bar--');
14115      * // => 'fooBar'
14116      *
14117      * _.camelCase('__FOO_BAR__');
14118      * // => 'fooBar'
14119      */
14120     var camelCase = createCompounder(function(result, word, index) {
14121       word = word.toLowerCase();
14122       return result + (index ? capitalize(word) : word);
14123     });
14124
14125     /**
14126      * Converts the first character of `string` to upper case and the remaining
14127      * to lower case.
14128      *
14129      * @static
14130      * @memberOf _
14131      * @since 3.0.0
14132      * @category String
14133      * @param {string} [string=''] The string to capitalize.
14134      * @returns {string} Returns the capitalized string.
14135      * @example
14136      *
14137      * _.capitalize('FRED');
14138      * // => 'Fred'
14139      */
14140     function capitalize(string) {
14141       return upperFirst(toString(string).toLowerCase());
14142     }
14143
14144     /**
14145      * Deburrs `string` by converting
14146      * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
14147      * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
14148      * letters to basic Latin letters and removing
14149      * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
14150      *
14151      * @static
14152      * @memberOf _
14153      * @since 3.0.0
14154      * @category String
14155      * @param {string} [string=''] The string to deburr.
14156      * @returns {string} Returns the deburred string.
14157      * @example
14158      *
14159      * _.deburr('déjà vu');
14160      * // => 'deja vu'
14161      */
14162     function deburr(string) {
14163       string = toString(string);
14164       return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
14165     }
14166
14167     /**
14168      * Checks if `string` ends with the given target string.
14169      *
14170      * @static
14171      * @memberOf _
14172      * @since 3.0.0
14173      * @category String
14174      * @param {string} [string=''] The string to inspect.
14175      * @param {string} [target] The string to search for.
14176      * @param {number} [position=string.length] The position to search up to.
14177      * @returns {boolean} Returns `true` if `string` ends with `target`,
14178      *  else `false`.
14179      * @example
14180      *
14181      * _.endsWith('abc', 'c');
14182      * // => true
14183      *
14184      * _.endsWith('abc', 'b');
14185      * // => false
14186      *
14187      * _.endsWith('abc', 'b', 2);
14188      * // => true
14189      */
14190     function endsWith(string, target, position) {
14191       string = toString(string);
14192       target = baseToString(target);
14193
14194       var length = string.length;
14195       position = position === undefined
14196         ? length
14197         : baseClamp(toInteger(position), 0, length);
14198
14199       var end = position;
14200       position -= target.length;
14201       return position >= 0 && string.slice(position, end) == target;
14202     }
14203
14204     /**
14205      * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
14206      * corresponding HTML entities.
14207      *
14208      * **Note:** No other characters are escaped. To escape additional
14209      * characters use a third-party library like [_he_](https://mths.be/he).
14210      *
14211      * Though the ">" character is escaped for symmetry, characters like
14212      * ">" and "/" don't need escaping in HTML and have no special meaning
14213      * unless they're part of a tag or unquoted attribute value. See
14214      * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
14215      * (under "semi-related fun fact") for more details.
14216      *
14217      * When working with HTML you should always
14218      * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
14219      * XSS vectors.
14220      *
14221      * @static
14222      * @since 0.1.0
14223      * @memberOf _
14224      * @category String
14225      * @param {string} [string=''] The string to escape.
14226      * @returns {string} Returns the escaped string.
14227      * @example
14228      *
14229      * _.escape('fred, barney, & pebbles');
14230      * // => 'fred, barney, &amp; pebbles'
14231      */
14232     function escape(string) {
14233       string = toString(string);
14234       return (string && reHasUnescapedHtml.test(string))
14235         ? string.replace(reUnescapedHtml, escapeHtmlChar)
14236         : string;
14237     }
14238
14239     /**
14240      * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
14241      * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
14242      *
14243      * @static
14244      * @memberOf _
14245      * @since 3.0.0
14246      * @category String
14247      * @param {string} [string=''] The string to escape.
14248      * @returns {string} Returns the escaped string.
14249      * @example
14250      *
14251      * _.escapeRegExp('[lodash](https://lodash.com/)');
14252      * // => '\[lodash\]\(https://lodash\.com/\)'
14253      */
14254     function escapeRegExp(string) {
14255       string = toString(string);
14256       return (string && reHasRegExpChar.test(string))
14257         ? string.replace(reRegExpChar, '\\$&')
14258         : string;
14259     }
14260
14261     /**
14262      * Converts `string` to
14263      * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
14264      *
14265      * @static
14266      * @memberOf _
14267      * @since 3.0.0
14268      * @category String
14269      * @param {string} [string=''] The string to convert.
14270      * @returns {string} Returns the kebab cased string.
14271      * @example
14272      *
14273      * _.kebabCase('Foo Bar');
14274      * // => 'foo-bar'
14275      *
14276      * _.kebabCase('fooBar');
14277      * // => 'foo-bar'
14278      *
14279      * _.kebabCase('__FOO_BAR__');
14280      * // => 'foo-bar'
14281      */
14282     var kebabCase = createCompounder(function(result, word, index) {
14283       return result + (index ? '-' : '') + word.toLowerCase();
14284     });
14285
14286     /**
14287      * Converts `string`, as space separated words, to lower case.
14288      *
14289      * @static
14290      * @memberOf _
14291      * @since 4.0.0
14292      * @category String
14293      * @param {string} [string=''] The string to convert.
14294      * @returns {string} Returns the lower cased string.
14295      * @example
14296      *
14297      * _.lowerCase('--Foo-Bar--');
14298      * // => 'foo bar'
14299      *
14300      * _.lowerCase('fooBar');
14301      * // => 'foo bar'
14302      *
14303      * _.lowerCase('__FOO_BAR__');
14304      * // => 'foo bar'
14305      */
14306     var lowerCase = createCompounder(function(result, word, index) {
14307       return result + (index ? ' ' : '') + word.toLowerCase();
14308     });
14309
14310     /**
14311      * Converts the first character of `string` to lower case.
14312      *
14313      * @static
14314      * @memberOf _
14315      * @since 4.0.0
14316      * @category String
14317      * @param {string} [string=''] The string to convert.
14318      * @returns {string} Returns the converted string.
14319      * @example
14320      *
14321      * _.lowerFirst('Fred');
14322      * // => 'fred'
14323      *
14324      * _.lowerFirst('FRED');
14325      * // => 'fRED'
14326      */
14327     var lowerFirst = createCaseFirst('toLowerCase');
14328
14329     /**
14330      * Pads `string` on the left and right sides if it's shorter than `length`.
14331      * Padding characters are truncated if they can't be evenly divided by `length`.
14332      *
14333      * @static
14334      * @memberOf _
14335      * @since 3.0.0
14336      * @category String
14337      * @param {string} [string=''] The string to pad.
14338      * @param {number} [length=0] The padding length.
14339      * @param {string} [chars=' '] The string used as padding.
14340      * @returns {string} Returns the padded string.
14341      * @example
14342      *
14343      * _.pad('abc', 8);
14344      * // => '  abc   '
14345      *
14346      * _.pad('abc', 8, '_-');
14347      * // => '_-abc_-_'
14348      *
14349      * _.pad('abc', 3);
14350      * // => 'abc'
14351      */
14352     function pad(string, length, chars) {
14353       string = toString(string);
14354       length = toInteger(length);
14355
14356       var strLength = length ? stringSize(string) : 0;
14357       if (!length || strLength >= length) {
14358         return string;
14359       }
14360       var mid = (length - strLength) / 2;
14361       return (
14362         createPadding(nativeFloor(mid), chars) +
14363         string +
14364         createPadding(nativeCeil(mid), chars)
14365       );
14366     }
14367
14368     /**
14369      * Pads `string` on the right side if it's shorter than `length`. Padding
14370      * characters are truncated if they exceed `length`.
14371      *
14372      * @static
14373      * @memberOf _
14374      * @since 4.0.0
14375      * @category String
14376      * @param {string} [string=''] The string to pad.
14377      * @param {number} [length=0] The padding length.
14378      * @param {string} [chars=' '] The string used as padding.
14379      * @returns {string} Returns the padded string.
14380      * @example
14381      *
14382      * _.padEnd('abc', 6);
14383      * // => 'abc   '
14384      *
14385      * _.padEnd('abc', 6, '_-');
14386      * // => 'abc_-_'
14387      *
14388      * _.padEnd('abc', 3);
14389      * // => 'abc'
14390      */
14391     function padEnd(string, length, chars) {
14392       string = toString(string);
14393       length = toInteger(length);
14394
14395       var strLength = length ? stringSize(string) : 0;
14396       return (length && strLength < length)
14397         ? (string + createPadding(length - strLength, chars))
14398         : string;
14399     }
14400
14401     /**
14402      * Pads `string` on the left side if it's shorter than `length`. Padding
14403      * characters are truncated if they exceed `length`.
14404      *
14405      * @static
14406      * @memberOf _
14407      * @since 4.0.0
14408      * @category String
14409      * @param {string} [string=''] The string to pad.
14410      * @param {number} [length=0] The padding length.
14411      * @param {string} [chars=' '] The string used as padding.
14412      * @returns {string} Returns the padded string.
14413      * @example
14414      *
14415      * _.padStart('abc', 6);
14416      * // => '   abc'
14417      *
14418      * _.padStart('abc', 6, '_-');
14419      * // => '_-_abc'
14420      *
14421      * _.padStart('abc', 3);
14422      * // => 'abc'
14423      */
14424     function padStart(string, length, chars) {
14425       string = toString(string);
14426       length = toInteger(length);
14427
14428       var strLength = length ? stringSize(string) : 0;
14429       return (length && strLength < length)
14430         ? (createPadding(length - strLength, chars) + string)
14431         : string;
14432     }
14433
14434     /**
14435      * Converts `string` to an integer of the specified radix. If `radix` is
14436      * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
14437      * hexadecimal, in which case a `radix` of `16` is used.
14438      *
14439      * **Note:** This method aligns with the
14440      * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
14441      *
14442      * @static
14443      * @memberOf _
14444      * @since 1.1.0
14445      * @category String
14446      * @param {string} string The string to convert.
14447      * @param {number} [radix=10] The radix to interpret `value` by.
14448      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14449      * @returns {number} Returns the converted integer.
14450      * @example
14451      *
14452      * _.parseInt('08');
14453      * // => 8
14454      *
14455      * _.map(['6', '08', '10'], _.parseInt);
14456      * // => [6, 8, 10]
14457      */
14458     function parseInt(string, radix, guard) {
14459       if (guard || radix == null) {
14460         radix = 0;
14461       } else if (radix) {
14462         radix = +radix;
14463       }
14464       return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
14465     }
14466
14467     /**
14468      * Repeats the given string `n` times.
14469      *
14470      * @static
14471      * @memberOf _
14472      * @since 3.0.0
14473      * @category String
14474      * @param {string} [string=''] The string to repeat.
14475      * @param {number} [n=1] The number of times to repeat the string.
14476      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14477      * @returns {string} Returns the repeated string.
14478      * @example
14479      *
14480      * _.repeat('*', 3);
14481      * // => '***'
14482      *
14483      * _.repeat('abc', 2);
14484      * // => 'abcabc'
14485      *
14486      * _.repeat('abc', 0);
14487      * // => ''
14488      */
14489     function repeat(string, n, guard) {
14490       if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
14491         n = 1;
14492       } else {
14493         n = toInteger(n);
14494       }
14495       return baseRepeat(toString(string), n);
14496     }
14497
14498     /**
14499      * Replaces matches for `pattern` in `string` with `replacement`.
14500      *
14501      * **Note:** This method is based on
14502      * [`String#replace`](https://mdn.io/String/replace).
14503      *
14504      * @static
14505      * @memberOf _
14506      * @since 4.0.0
14507      * @category String
14508      * @param {string} [string=''] The string to modify.
14509      * @param {RegExp|string} pattern The pattern to replace.
14510      * @param {Function|string} replacement The match replacement.
14511      * @returns {string} Returns the modified string.
14512      * @example
14513      *
14514      * _.replace('Hi Fred', 'Fred', 'Barney');
14515      * // => 'Hi Barney'
14516      */
14517     function replace() {
14518       var args = arguments,
14519           string = toString(args[0]);
14520
14521       return args.length < 3 ? string : string.replace(args[1], args[2]);
14522     }
14523
14524     /**
14525      * Converts `string` to
14526      * [snake case](https://en.wikipedia.org/wiki/Snake_case).
14527      *
14528      * @static
14529      * @memberOf _
14530      * @since 3.0.0
14531      * @category String
14532      * @param {string} [string=''] The string to convert.
14533      * @returns {string} Returns the snake cased string.
14534      * @example
14535      *
14536      * _.snakeCase('Foo Bar');
14537      * // => 'foo_bar'
14538      *
14539      * _.snakeCase('fooBar');
14540      * // => 'foo_bar'
14541      *
14542      * _.snakeCase('--FOO-BAR--');
14543      * // => 'foo_bar'
14544      */
14545     var snakeCase = createCompounder(function(result, word, index) {
14546       return result + (index ? '_' : '') + word.toLowerCase();
14547     });
14548
14549     /**
14550      * Splits `string` by `separator`.
14551      *
14552      * **Note:** This method is based on
14553      * [`String#split`](https://mdn.io/String/split).
14554      *
14555      * @static
14556      * @memberOf _
14557      * @since 4.0.0
14558      * @category String
14559      * @param {string} [string=''] The string to split.
14560      * @param {RegExp|string} separator The separator pattern to split by.
14561      * @param {number} [limit] The length to truncate results to.
14562      * @returns {Array} Returns the string segments.
14563      * @example
14564      *
14565      * _.split('a-b-c', '-', 2);
14566      * // => ['a', 'b']
14567      */
14568     function split(string, separator, limit) {
14569       if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
14570         separator = limit = undefined;
14571       }
14572       limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
14573       if (!limit) {
14574         return [];
14575       }
14576       string = toString(string);
14577       if (string && (
14578             typeof separator == 'string' ||
14579             (separator != null && !isRegExp(separator))
14580           )) {
14581         separator = baseToString(separator);
14582         if (!separator && hasUnicode(string)) {
14583           return castSlice(stringToArray(string), 0, limit);
14584         }
14585       }
14586       return string.split(separator, limit);
14587     }
14588
14589     /**
14590      * Converts `string` to
14591      * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
14592      *
14593      * @static
14594      * @memberOf _
14595      * @since 3.1.0
14596      * @category String
14597      * @param {string} [string=''] The string to convert.
14598      * @returns {string} Returns the start cased string.
14599      * @example
14600      *
14601      * _.startCase('--foo-bar--');
14602      * // => 'Foo Bar'
14603      *
14604      * _.startCase('fooBar');
14605      * // => 'Foo Bar'
14606      *
14607      * _.startCase('__FOO_BAR__');
14608      * // => 'FOO BAR'
14609      */
14610     var startCase = createCompounder(function(result, word, index) {
14611       return result + (index ? ' ' : '') + upperFirst(word);
14612     });
14613
14614     /**
14615      * Checks if `string` starts with the given target string.
14616      *
14617      * @static
14618      * @memberOf _
14619      * @since 3.0.0
14620      * @category String
14621      * @param {string} [string=''] The string to inspect.
14622      * @param {string} [target] The string to search for.
14623      * @param {number} [position=0] The position to search from.
14624      * @returns {boolean} Returns `true` if `string` starts with `target`,
14625      *  else `false`.
14626      * @example
14627      *
14628      * _.startsWith('abc', 'a');
14629      * // => true
14630      *
14631      * _.startsWith('abc', 'b');
14632      * // => false
14633      *
14634      * _.startsWith('abc', 'b', 1);
14635      * // => true
14636      */
14637     function startsWith(string, target, position) {
14638       string = toString(string);
14639       position = baseClamp(toInteger(position), 0, string.length);
14640       target = baseToString(target);
14641       return string.slice(position, position + target.length) == target;
14642     }
14643
14644     /**
14645      * Creates a compiled template function that can interpolate data properties
14646      * in "interpolate" delimiters, HTML-escape interpolated data properties in
14647      * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
14648      * properties may be accessed as free variables in the template. If a setting
14649      * object is given, it takes precedence over `_.templateSettings` values.
14650      *
14651      * **Note:** In the development build `_.template` utilizes
14652      * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
14653      * for easier debugging.
14654      *
14655      * For more information on precompiling templates see
14656      * [lodash's custom builds documentation](https://lodash.com/custom-builds).
14657      *
14658      * For more information on Chrome extension sandboxes see
14659      * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
14660      *
14661      * @static
14662      * @since 0.1.0
14663      * @memberOf _
14664      * @category String
14665      * @param {string} [string=''] The template string.
14666      * @param {Object} [options={}] The options object.
14667      * @param {RegExp} [options.escape=_.templateSettings.escape]
14668      *  The HTML "escape" delimiter.
14669      * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
14670      *  The "evaluate" delimiter.
14671      * @param {Object} [options.imports=_.templateSettings.imports]
14672      *  An object to import into the template as free variables.
14673      * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
14674      *  The "interpolate" delimiter.
14675      * @param {string} [options.sourceURL='lodash.templateSources[n]']
14676      *  The sourceURL of the compiled template.
14677      * @param {string} [options.variable='obj']
14678      *  The data object variable name.
14679      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14680      * @returns {Function} Returns the compiled template function.
14681      * @example
14682      *
14683      * // Use the "interpolate" delimiter to create a compiled template.
14684      * var compiled = _.template('hello <%= user %>!');
14685      * compiled({ 'user': 'fred' });
14686      * // => 'hello fred!'
14687      *
14688      * // Use the HTML "escape" delimiter to escape data property values.
14689      * var compiled = _.template('<b><%- value %></b>');
14690      * compiled({ 'value': '<script>' });
14691      * // => '<b>&lt;script&gt;</b>'
14692      *
14693      * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
14694      * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
14695      * compiled({ 'users': ['fred', 'barney'] });
14696      * // => '<li>fred</li><li>barney</li>'
14697      *
14698      * // Use the internal `print` function in "evaluate" delimiters.
14699      * var compiled = _.template('<% print("hello " + user); %>!');
14700      * compiled({ 'user': 'barney' });
14701      * // => 'hello barney!'
14702      *
14703      * // Use the ES template literal delimiter as an "interpolate" delimiter.
14704      * // Disable support by replacing the "interpolate" delimiter.
14705      * var compiled = _.template('hello ${ user }!');
14706      * compiled({ 'user': 'pebbles' });
14707      * // => 'hello pebbles!'
14708      *
14709      * // Use backslashes to treat delimiters as plain text.
14710      * var compiled = _.template('<%= "\\<%- value %\\>" %>');
14711      * compiled({ 'value': 'ignored' });
14712      * // => '<%- value %>'
14713      *
14714      * // Use the `imports` option to import `jQuery` as `jq`.
14715      * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
14716      * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
14717      * compiled({ 'users': ['fred', 'barney'] });
14718      * // => '<li>fred</li><li>barney</li>'
14719      *
14720      * // Use the `sourceURL` option to specify a custom sourceURL for the template.
14721      * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
14722      * compiled(data);
14723      * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
14724      *
14725      * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
14726      * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
14727      * compiled.source;
14728      * // => function(data) {
14729      * //   var __t, __p = '';
14730      * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
14731      * //   return __p;
14732      * // }
14733      *
14734      * // Use custom template delimiters.
14735      * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
14736      * var compiled = _.template('hello {{ user }}!');
14737      * compiled({ 'user': 'mustache' });
14738      * // => 'hello mustache!'
14739      *
14740      * // Use the `source` property to inline compiled templates for meaningful
14741      * // line numbers in error messages and stack traces.
14742      * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
14743      *   var JST = {\
14744      *     "main": ' + _.template(mainText).source + '\
14745      *   };\
14746      * ');
14747      */
14748     function template(string, options, guard) {
14749       // Based on John Resig's `tmpl` implementation
14750       // (http://ejohn.org/blog/javascript-micro-templating/)
14751       // and Laura Doktorova's doT.js (https://github.com/olado/doT).
14752       var settings = lodash.templateSettings;
14753
14754       if (guard && isIterateeCall(string, options, guard)) {
14755         options = undefined;
14756       }
14757       string = toString(string);
14758       options = assignInWith({}, options, settings, assignInDefaults);
14759
14760       var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
14761           importsKeys = keys(imports),
14762           importsValues = baseValues(imports, importsKeys);
14763
14764       var isEscaping,
14765           isEvaluating,
14766           index = 0,
14767           interpolate = options.interpolate || reNoMatch,
14768           source = "__p += '";
14769
14770       // Compile the regexp to match each delimiter.
14771       var reDelimiters = RegExp(
14772         (options.escape || reNoMatch).source + '|' +
14773         interpolate.source + '|' +
14774         (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
14775         (options.evaluate || reNoMatch).source + '|$'
14776       , 'g');
14777
14778       // Use a sourceURL for easier debugging.
14779       var sourceURL = '//# sourceURL=' +
14780         ('sourceURL' in options
14781           ? options.sourceURL
14782           : ('lodash.templateSources[' + (++templateCounter) + ']')
14783         ) + '\n';
14784
14785       string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
14786         interpolateValue || (interpolateValue = esTemplateValue);
14787
14788         // Escape characters that can't be included in string literals.
14789         source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
14790
14791         // Replace delimiters with snippets.
14792         if (escapeValue) {
14793           isEscaping = true;
14794           source += "' +\n__e(" + escapeValue + ") +\n'";
14795         }
14796         if (evaluateValue) {
14797           isEvaluating = true;
14798           source += "';\n" + evaluateValue + ";\n__p += '";
14799         }
14800         if (interpolateValue) {
14801           source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
14802         }
14803         index = offset + match.length;
14804
14805         // The JS engine embedded in Adobe products needs `match` returned in
14806         // order to produce the correct `offset` value.
14807         return match;
14808       });
14809
14810       source += "';\n";
14811
14812       // If `variable` is not specified wrap a with-statement around the generated
14813       // code to add the data object to the top of the scope chain.
14814       var variable = options.variable;
14815       if (!variable) {
14816         source = 'with (obj) {\n' + source + '\n}\n';
14817       }
14818       // Cleanup code by stripping empty strings.
14819       source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
14820         .replace(reEmptyStringMiddle, '$1')
14821         .replace(reEmptyStringTrailing, '$1;');
14822
14823       // Frame code as the function body.
14824       source = 'function(' + (variable || 'obj') + ') {\n' +
14825         (variable
14826           ? ''
14827           : 'obj || (obj = {});\n'
14828         ) +
14829         "var __t, __p = ''" +
14830         (isEscaping
14831            ? ', __e = _.escape'
14832            : ''
14833         ) +
14834         (isEvaluating
14835           ? ', __j = Array.prototype.join;\n' +
14836             "function print() { __p += __j.call(arguments, '') }\n"
14837           : ';\n'
14838         ) +
14839         source +
14840         'return __p\n}';
14841
14842       var result = attempt(function() {
14843         return Function(importsKeys, sourceURL + 'return ' + source)
14844           .apply(undefined, importsValues);
14845       });
14846
14847       // Provide the compiled function's source by its `toString` method or
14848       // the `source` property as a convenience for inlining compiled templates.
14849       result.source = source;
14850       if (isError(result)) {
14851         throw result;
14852       }
14853       return result;
14854     }
14855
14856     /**
14857      * Converts `string`, as a whole, to lower case just like
14858      * [String#toLowerCase](https://mdn.io/toLowerCase).
14859      *
14860      * @static
14861      * @memberOf _
14862      * @since 4.0.0
14863      * @category String
14864      * @param {string} [string=''] The string to convert.
14865      * @returns {string} Returns the lower cased string.
14866      * @example
14867      *
14868      * _.toLower('--Foo-Bar--');
14869      * // => '--foo-bar--'
14870      *
14871      * _.toLower('fooBar');
14872      * // => 'foobar'
14873      *
14874      * _.toLower('__FOO_BAR__');
14875      * // => '__foo_bar__'
14876      */
14877     function toLower(value) {
14878       return toString(value).toLowerCase();
14879     }
14880
14881     /**
14882      * Converts `string`, as a whole, to upper case just like
14883      * [String#toUpperCase](https://mdn.io/toUpperCase).
14884      *
14885      * @static
14886      * @memberOf _
14887      * @since 4.0.0
14888      * @category String
14889      * @param {string} [string=''] The string to convert.
14890      * @returns {string} Returns the upper cased string.
14891      * @example
14892      *
14893      * _.toUpper('--foo-bar--');
14894      * // => '--FOO-BAR--'
14895      *
14896      * _.toUpper('fooBar');
14897      * // => 'FOOBAR'
14898      *
14899      * _.toUpper('__foo_bar__');
14900      * // => '__FOO_BAR__'
14901      */
14902     function toUpper(value) {
14903       return toString(value).toUpperCase();
14904     }
14905
14906     /**
14907      * Removes leading and trailing whitespace or specified characters from `string`.
14908      *
14909      * @static
14910      * @memberOf _
14911      * @since 3.0.0
14912      * @category String
14913      * @param {string} [string=''] The string to trim.
14914      * @param {string} [chars=whitespace] The characters to trim.
14915      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14916      * @returns {string} Returns the trimmed string.
14917      * @example
14918      *
14919      * _.trim('  abc  ');
14920      * // => 'abc'
14921      *
14922      * _.trim('-_-abc-_-', '_-');
14923      * // => 'abc'
14924      *
14925      * _.map(['  foo  ', '  bar  '], _.trim);
14926      * // => ['foo', 'bar']
14927      */
14928     function trim(string, chars, guard) {
14929       string = toString(string);
14930       if (string && (guard || chars === undefined)) {
14931         return string.replace(reTrim, '');
14932       }
14933       if (!string || !(chars = baseToString(chars))) {
14934         return string;
14935       }
14936       var strSymbols = stringToArray(string),
14937           chrSymbols = stringToArray(chars),
14938           start = charsStartIndex(strSymbols, chrSymbols),
14939           end = charsEndIndex(strSymbols, chrSymbols) + 1;
14940
14941       return castSlice(strSymbols, start, end).join('');
14942     }
14943
14944     /**
14945      * Removes trailing whitespace or specified characters from `string`.
14946      *
14947      * @static
14948      * @memberOf _
14949      * @since 4.0.0
14950      * @category String
14951      * @param {string} [string=''] The string to trim.
14952      * @param {string} [chars=whitespace] The characters to trim.
14953      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14954      * @returns {string} Returns the trimmed string.
14955      * @example
14956      *
14957      * _.trimEnd('  abc  ');
14958      * // => '  abc'
14959      *
14960      * _.trimEnd('-_-abc-_-', '_-');
14961      * // => '-_-abc'
14962      */
14963     function trimEnd(string, chars, guard) {
14964       string = toString(string);
14965       if (string && (guard || chars === undefined)) {
14966         return string.replace(reTrimEnd, '');
14967       }
14968       if (!string || !(chars = baseToString(chars))) {
14969         return string;
14970       }
14971       var strSymbols = stringToArray(string),
14972           end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
14973
14974       return castSlice(strSymbols, 0, end).join('');
14975     }
14976
14977     /**
14978      * Removes leading whitespace or specified characters from `string`.
14979      *
14980      * @static
14981      * @memberOf _
14982      * @since 4.0.0
14983      * @category String
14984      * @param {string} [string=''] The string to trim.
14985      * @param {string} [chars=whitespace] The characters to trim.
14986      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14987      * @returns {string} Returns the trimmed string.
14988      * @example
14989      *
14990      * _.trimStart('  abc  ');
14991      * // => 'abc  '
14992      *
14993      * _.trimStart('-_-abc-_-', '_-');
14994      * // => 'abc-_-'
14995      */
14996     function trimStart(string, chars, guard) {
14997       string = toString(string);
14998       if (string && (guard || chars === undefined)) {
14999         return string.replace(reTrimStart, '');
15000       }
15001       if (!string || !(chars = baseToString(chars))) {
15002         return string;
15003       }
15004       var strSymbols = stringToArray(string),
15005           start = charsStartIndex(strSymbols, stringToArray(chars));
15006
15007       return castSlice(strSymbols, start).join('');
15008     }
15009
15010     /**
15011      * Truncates `string` if it's longer than the given maximum string length.
15012      * The last characters of the truncated string are replaced with the omission
15013      * string which defaults to "...".
15014      *
15015      * @static
15016      * @memberOf _
15017      * @since 4.0.0
15018      * @category String
15019      * @param {string} [string=''] The string to truncate.
15020      * @param {Object} [options={}] The options object.
15021      * @param {number} [options.length=30] The maximum string length.
15022      * @param {string} [options.omission='...'] The string to indicate text is omitted.
15023      * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
15024      * @returns {string} Returns the truncated string.
15025      * @example
15026      *
15027      * _.truncate('hi-diddly-ho there, neighborino');
15028      * // => 'hi-diddly-ho there, neighbo...'
15029      *
15030      * _.truncate('hi-diddly-ho there, neighborino', {
15031      *   'length': 24,
15032      *   'separator': ' '
15033      * });
15034      * // => 'hi-diddly-ho there,...'
15035      *
15036      * _.truncate('hi-diddly-ho there, neighborino', {
15037      *   'length': 24,
15038      *   'separator': /,? +/
15039      * });
15040      * // => 'hi-diddly-ho there...'
15041      *
15042      * _.truncate('hi-diddly-ho there, neighborino', {
15043      *   'omission': ' [...]'
15044      * });
15045      * // => 'hi-diddly-ho there, neig [...]'
15046      */
15047     function truncate(string, options) {
15048       var length = DEFAULT_TRUNC_LENGTH,
15049           omission = DEFAULT_TRUNC_OMISSION;
15050
15051       if (isObject(options)) {
15052         var separator = 'separator' in options ? options.separator : separator;
15053         length = 'length' in options ? toInteger(options.length) : length;
15054         omission = 'omission' in options ? baseToString(options.omission) : omission;
15055       }
15056       string = toString(string);
15057
15058       var strLength = string.length;
15059       if (hasUnicode(string)) {
15060         var strSymbols = stringToArray(string);
15061         strLength = strSymbols.length;
15062       }
15063       if (length >= strLength) {
15064         return string;
15065       }
15066       var end = length - stringSize(omission);
15067       if (end < 1) {
15068         return omission;
15069       }
15070       var result = strSymbols
15071         ? castSlice(strSymbols, 0, end).join('')
15072         : string.slice(0, end);
15073
15074       if (separator === undefined) {
15075         return result + omission;
15076       }
15077       if (strSymbols) {
15078         end += (result.length - end);
15079       }
15080       if (isRegExp(separator)) {
15081         if (string.slice(end).search(separator)) {
15082           var match,
15083               substring = result;
15084
15085           if (!separator.global) {
15086             separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
15087           }
15088           separator.lastIndex = 0;
15089           while ((match = separator.exec(substring))) {
15090             var newEnd = match.index;
15091           }
15092           result = result.slice(0, newEnd === undefined ? end : newEnd);
15093         }
15094       } else if (string.indexOf(baseToString(separator), end) != end) {
15095         var index = result.lastIndexOf(separator);
15096         if (index > -1) {
15097           result = result.slice(0, index);
15098         }
15099       }
15100       return result + omission;
15101     }
15102
15103     /**
15104      * The inverse of `_.escape`; this method converts the HTML entities
15105      * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
15106      * their corresponding characters.
15107      *
15108      * **Note:** No other HTML entities are unescaped. To unescape additional
15109      * HTML entities use a third-party library like [_he_](https://mths.be/he).
15110      *
15111      * @static
15112      * @memberOf _
15113      * @since 0.6.0
15114      * @category String
15115      * @param {string} [string=''] The string to unescape.
15116      * @returns {string} Returns the unescaped string.
15117      * @example
15118      *
15119      * _.unescape('fred, barney, &amp; pebbles');
15120      * // => 'fred, barney, & pebbles'
15121      */
15122     function unescape(string) {
15123       string = toString(string);
15124       return (string && reHasEscapedHtml.test(string))
15125         ? string.replace(reEscapedHtml, unescapeHtmlChar)
15126         : string;
15127     }
15128
15129     /**
15130      * Converts `string`, as space separated words, to upper case.
15131      *
15132      * @static
15133      * @memberOf _
15134      * @since 4.0.0
15135      * @category String
15136      * @param {string} [string=''] The string to convert.
15137      * @returns {string} Returns the upper cased string.
15138      * @example
15139      *
15140      * _.upperCase('--foo-bar');
15141      * // => 'FOO BAR'
15142      *
15143      * _.upperCase('fooBar');
15144      * // => 'FOO BAR'
15145      *
15146      * _.upperCase('__foo_bar__');
15147      * // => 'FOO BAR'
15148      */
15149     var upperCase = createCompounder(function(result, word, index) {
15150       return result + (index ? ' ' : '') + word.toUpperCase();
15151     });
15152
15153     /**
15154      * Converts the first character of `string` to upper case.
15155      *
15156      * @static
15157      * @memberOf _
15158      * @since 4.0.0
15159      * @category String
15160      * @param {string} [string=''] The string to convert.
15161      * @returns {string} Returns the converted string.
15162      * @example
15163      *
15164      * _.upperFirst('fred');
15165      * // => 'Fred'
15166      *
15167      * _.upperFirst('FRED');
15168      * // => 'FRED'
15169      */
15170     var upperFirst = createCaseFirst('toUpperCase');
15171
15172     /**
15173      * Splits `string` into an array of its words.
15174      *
15175      * @static
15176      * @memberOf _
15177      * @since 3.0.0
15178      * @category String
15179      * @param {string} [string=''] The string to inspect.
15180      * @param {RegExp|string} [pattern] The pattern to match words.
15181      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15182      * @returns {Array} Returns the words of `string`.
15183      * @example
15184      *
15185      * _.words('fred, barney, & pebbles');
15186      * // => ['fred', 'barney', 'pebbles']
15187      *
15188      * _.words('fred, barney, & pebbles', /[^, ]+/g);
15189      * // => ['fred', 'barney', '&', 'pebbles']
15190      */
15191     function words(string, pattern, guard) {
15192       string = toString(string);
15193       pattern = guard ? undefined : pattern;
15194
15195       if (pattern === undefined) {
15196         return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
15197       }
15198       return string.match(pattern) || [];
15199     }
15200
15201     /*------------------------------------------------------------------------*/
15202
15203     /**
15204      * Attempts to invoke `func`, returning either the result or the caught error
15205      * object. Any additional arguments are provided to `func` when it's invoked.
15206      *
15207      * @static
15208      * @memberOf _
15209      * @since 3.0.0
15210      * @category Util
15211      * @param {Function} func The function to attempt.
15212      * @param {...*} [args] The arguments to invoke `func` with.
15213      * @returns {*} Returns the `func` result or error object.
15214      * @example
15215      *
15216      * // Avoid throwing errors for invalid selectors.
15217      * var elements = _.attempt(function(selector) {
15218      *   return document.querySelectorAll(selector);
15219      * }, '>_>');
15220      *
15221      * if (_.isError(elements)) {
15222      *   elements = [];
15223      * }
15224      */
15225     var attempt = baseRest(function(func, args) {
15226       try {
15227         return apply(func, undefined, args);
15228       } catch (e) {
15229         return isError(e) ? e : new Error(e);
15230       }
15231     });
15232
15233     /**
15234      * Binds methods of an object to the object itself, overwriting the existing
15235      * method.
15236      *
15237      * **Note:** This method doesn't set the "length" property of bound functions.
15238      *
15239      * @static
15240      * @since 0.1.0
15241      * @memberOf _
15242      * @category Util
15243      * @param {Object} object The object to bind and assign the bound methods to.
15244      * @param {...(string|string[])} methodNames The object method names to bind.
15245      * @returns {Object} Returns `object`.
15246      * @example
15247      *
15248      * var view = {
15249      *   'label': 'docs',
15250      *   'click': function() {
15251      *     console.log('clicked ' + this.label);
15252      *   }
15253      * };
15254      *
15255      * _.bindAll(view, ['click']);
15256      * jQuery(element).on('click', view.click);
15257      * // => Logs 'clicked docs' when clicked.
15258      */
15259     var bindAll = flatRest(function(object, methodNames) {
15260       arrayEach(methodNames, function(key) {
15261         key = toKey(key);
15262         baseAssignValue(object, key, bind(object[key], object));
15263       });
15264       return object;
15265     });
15266
15267     /**
15268      * Creates a function that iterates over `pairs` and invokes the corresponding
15269      * function of the first predicate to return truthy. The predicate-function
15270      * pairs are invoked with the `this` binding and arguments of the created
15271      * function.
15272      *
15273      * @static
15274      * @memberOf _
15275      * @since 4.0.0
15276      * @category Util
15277      * @param {Array} pairs The predicate-function pairs.
15278      * @returns {Function} Returns the new composite function.
15279      * @example
15280      *
15281      * var func = _.cond([
15282      *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
15283      *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
15284      *   [_.stubTrue,                      _.constant('no match')]
15285      * ]);
15286      *
15287      * func({ 'a': 1, 'b': 2 });
15288      * // => 'matches A'
15289      *
15290      * func({ 'a': 0, 'b': 1 });
15291      * // => 'matches B'
15292      *
15293      * func({ 'a': '1', 'b': '2' });
15294      * // => 'no match'
15295      */
15296     function cond(pairs) {
15297       var length = pairs == null ? 0 : pairs.length,
15298           toIteratee = getIteratee();
15299
15300       pairs = !length ? [] : arrayMap(pairs, function(pair) {
15301         if (typeof pair[1] != 'function') {
15302           throw new TypeError(FUNC_ERROR_TEXT);
15303         }
15304         return [toIteratee(pair[0]), pair[1]];
15305       });
15306
15307       return baseRest(function(args) {
15308         var index = -1;
15309         while (++index < length) {
15310           var pair = pairs[index];
15311           if (apply(pair[0], this, args)) {
15312             return apply(pair[1], this, args);
15313           }
15314         }
15315       });
15316     }
15317
15318     /**
15319      * Creates a function that invokes the predicate properties of `source` with
15320      * the corresponding property values of a given object, returning `true` if
15321      * all predicates return truthy, else `false`.
15322      *
15323      * **Note:** The created function is equivalent to `_.conformsTo` with
15324      * `source` partially applied.
15325      *
15326      * @static
15327      * @memberOf _
15328      * @since 4.0.0
15329      * @category Util
15330      * @param {Object} source The object of property predicates to conform to.
15331      * @returns {Function} Returns the new spec function.
15332      * @example
15333      *
15334      * var objects = [
15335      *   { 'a': 2, 'b': 1 },
15336      *   { 'a': 1, 'b': 2 }
15337      * ];
15338      *
15339      * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
15340      * // => [{ 'a': 1, 'b': 2 }]
15341      */
15342     function conforms(source) {
15343       return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
15344     }
15345
15346     /**
15347      * Creates a function that returns `value`.
15348      *
15349      * @static
15350      * @memberOf _
15351      * @since 2.4.0
15352      * @category Util
15353      * @param {*} value The value to return from the new function.
15354      * @returns {Function} Returns the new constant function.
15355      * @example
15356      *
15357      * var objects = _.times(2, _.constant({ 'a': 1 }));
15358      *
15359      * console.log(objects);
15360      * // => [{ 'a': 1 }, { 'a': 1 }]
15361      *
15362      * console.log(objects[0] === objects[1]);
15363      * // => true
15364      */
15365     function constant(value) {
15366       return function() {
15367         return value;
15368       };
15369     }
15370
15371     /**
15372      * Checks `value` to determine whether a default value should be returned in
15373      * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
15374      * or `undefined`.
15375      *
15376      * @static
15377      * @memberOf _
15378      * @since 4.14.0
15379      * @category Util
15380      * @param {*} value The value to check.
15381      * @param {*} defaultValue The default value.
15382      * @returns {*} Returns the resolved value.
15383      * @example
15384      *
15385      * _.defaultTo(1, 10);
15386      * // => 1
15387      *
15388      * _.defaultTo(undefined, 10);
15389      * // => 10
15390      */
15391     function defaultTo(value, defaultValue) {
15392       return (value == null || value !== value) ? defaultValue : value;
15393     }
15394
15395     /**
15396      * Creates a function that returns the result of invoking the given functions
15397      * with the `this` binding of the created function, where each successive
15398      * invocation is supplied the return value of the previous.
15399      *
15400      * @static
15401      * @memberOf _
15402      * @since 3.0.0
15403      * @category Util
15404      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15405      * @returns {Function} Returns the new composite function.
15406      * @see _.flowRight
15407      * @example
15408      *
15409      * function square(n) {
15410      *   return n * n;
15411      * }
15412      *
15413      * var addSquare = _.flow([_.add, square]);
15414      * addSquare(1, 2);
15415      * // => 9
15416      */
15417     var flow = createFlow();
15418
15419     /**
15420      * This method is like `_.flow` except that it creates a function that
15421      * invokes the given functions from right to left.
15422      *
15423      * @static
15424      * @since 3.0.0
15425      * @memberOf _
15426      * @category Util
15427      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15428      * @returns {Function} Returns the new composite function.
15429      * @see _.flow
15430      * @example
15431      *
15432      * function square(n) {
15433      *   return n * n;
15434      * }
15435      *
15436      * var addSquare = _.flowRight([square, _.add]);
15437      * addSquare(1, 2);
15438      * // => 9
15439      */
15440     var flowRight = createFlow(true);
15441
15442     /**
15443      * This method returns the first argument it receives.
15444      *
15445      * @static
15446      * @since 0.1.0
15447      * @memberOf _
15448      * @category Util
15449      * @param {*} value Any value.
15450      * @returns {*} Returns `value`.
15451      * @example
15452      *
15453      * var object = { 'a': 1 };
15454      *
15455      * console.log(_.identity(object) === object);
15456      * // => true
15457      */
15458     function identity(value) {
15459       return value;
15460     }
15461
15462     /**
15463      * Creates a function that invokes `func` with the arguments of the created
15464      * function. If `func` is a property name, the created function returns the
15465      * property value for a given element. If `func` is an array or object, the
15466      * created function returns `true` for elements that contain the equivalent
15467      * source properties, otherwise it returns `false`.
15468      *
15469      * @static
15470      * @since 4.0.0
15471      * @memberOf _
15472      * @category Util
15473      * @param {*} [func=_.identity] The value to convert to a callback.
15474      * @returns {Function} Returns the callback.
15475      * @example
15476      *
15477      * var users = [
15478      *   { 'user': 'barney', 'age': 36, 'active': true },
15479      *   { 'user': 'fred',   'age': 40, 'active': false }
15480      * ];
15481      *
15482      * // The `_.matches` iteratee shorthand.
15483      * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
15484      * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
15485      *
15486      * // The `_.matchesProperty` iteratee shorthand.
15487      * _.filter(users, _.iteratee(['user', 'fred']));
15488      * // => [{ 'user': 'fred', 'age': 40 }]
15489      *
15490      * // The `_.property` iteratee shorthand.
15491      * _.map(users, _.iteratee('user'));
15492      * // => ['barney', 'fred']
15493      *
15494      * // Create custom iteratee shorthands.
15495      * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
15496      *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
15497      *     return func.test(string);
15498      *   };
15499      * });
15500      *
15501      * _.filter(['abc', 'def'], /ef/);
15502      * // => ['def']
15503      */
15504     function iteratee(func) {
15505       return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
15506     }
15507
15508     /**
15509      * Creates a function that performs a partial deep comparison between a given
15510      * object and `source`, returning `true` if the given object has equivalent
15511      * property values, else `false`.
15512      *
15513      * **Note:** The created function is equivalent to `_.isMatch` with `source`
15514      * partially applied.
15515      *
15516      * Partial comparisons will match empty array and empty object `source`
15517      * values against any array or object value, respectively. See `_.isEqual`
15518      * for a list of supported value comparisons.
15519      *
15520      * @static
15521      * @memberOf _
15522      * @since 3.0.0
15523      * @category Util
15524      * @param {Object} source The object of property values to match.
15525      * @returns {Function} Returns the new spec function.
15526      * @example
15527      *
15528      * var objects = [
15529      *   { 'a': 1, 'b': 2, 'c': 3 },
15530      *   { 'a': 4, 'b': 5, 'c': 6 }
15531      * ];
15532      *
15533      * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
15534      * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
15535      */
15536     function matches(source) {
15537       return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
15538     }
15539
15540     /**
15541      * Creates a function that performs a partial deep comparison between the
15542      * value at `path` of a given object to `srcValue`, returning `true` if the
15543      * object value is equivalent, else `false`.
15544      *
15545      * **Note:** Partial comparisons will match empty array and empty object
15546      * `srcValue` values against any array or object value, respectively. See
15547      * `_.isEqual` for a list of supported value comparisons.
15548      *
15549      * @static
15550      * @memberOf _
15551      * @since 3.2.0
15552      * @category Util
15553      * @param {Array|string} path The path of the property to get.
15554      * @param {*} srcValue The value to match.
15555      * @returns {Function} Returns the new spec function.
15556      * @example
15557      *
15558      * var objects = [
15559      *   { 'a': 1, 'b': 2, 'c': 3 },
15560      *   { 'a': 4, 'b': 5, 'c': 6 }
15561      * ];
15562      *
15563      * _.find(objects, _.matchesProperty('a', 4));
15564      * // => { 'a': 4, 'b': 5, 'c': 6 }
15565      */
15566     function matchesProperty(path, srcValue) {
15567       return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
15568     }
15569
15570     /**
15571      * Creates a function that invokes the method at `path` of a given object.
15572      * Any additional arguments are provided to the invoked method.
15573      *
15574      * @static
15575      * @memberOf _
15576      * @since 3.7.0
15577      * @category Util
15578      * @param {Array|string} path The path of the method to invoke.
15579      * @param {...*} [args] The arguments to invoke the method with.
15580      * @returns {Function} Returns the new invoker function.
15581      * @example
15582      *
15583      * var objects = [
15584      *   { 'a': { 'b': _.constant(2) } },
15585      *   { 'a': { 'b': _.constant(1) } }
15586      * ];
15587      *
15588      * _.map(objects, _.method('a.b'));
15589      * // => [2, 1]
15590      *
15591      * _.map(objects, _.method(['a', 'b']));
15592      * // => [2, 1]
15593      */
15594     var method = baseRest(function(path, args) {
15595       return function(object) {
15596         return baseInvoke(object, path, args);
15597       };
15598     });
15599
15600     /**
15601      * The opposite of `_.method`; this method creates a function that invokes
15602      * the method at a given path of `object`. Any additional arguments are
15603      * provided to the invoked method.
15604      *
15605      * @static
15606      * @memberOf _
15607      * @since 3.7.0
15608      * @category Util
15609      * @param {Object} object The object to query.
15610      * @param {...*} [args] The arguments to invoke the method with.
15611      * @returns {Function} Returns the new invoker function.
15612      * @example
15613      *
15614      * var array = _.times(3, _.constant),
15615      *     object = { 'a': array, 'b': array, 'c': array };
15616      *
15617      * _.map(['a[2]', 'c[0]'], _.methodOf(object));
15618      * // => [2, 0]
15619      *
15620      * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
15621      * // => [2, 0]
15622      */
15623     var methodOf = baseRest(function(object, args) {
15624       return function(path) {
15625         return baseInvoke(object, path, args);
15626       };
15627     });
15628
15629     /**
15630      * Adds all own enumerable string keyed function properties of a source
15631      * object to the destination object. If `object` is a function, then methods
15632      * are added to its prototype as well.
15633      *
15634      * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
15635      * avoid conflicts caused by modifying the original.
15636      *
15637      * @static
15638      * @since 0.1.0
15639      * @memberOf _
15640      * @category Util
15641      * @param {Function|Object} [object=lodash] The destination object.
15642      * @param {Object} source The object of functions to add.
15643      * @param {Object} [options={}] The options object.
15644      * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
15645      * @returns {Function|Object} Returns `object`.
15646      * @example
15647      *
15648      * function vowels(string) {
15649      *   return _.filter(string, function(v) {
15650      *     return /[aeiou]/i.test(v);
15651      *   });
15652      * }
15653      *
15654      * _.mixin({ 'vowels': vowels });
15655      * _.vowels('fred');
15656      * // => ['e']
15657      *
15658      * _('fred').vowels().value();
15659      * // => ['e']
15660      *
15661      * _.mixin({ 'vowels': vowels }, { 'chain': false });
15662      * _('fred').vowels();
15663      * // => ['e']
15664      */
15665     function mixin(object, source, options) {
15666       var props = keys(source),
15667           methodNames = baseFunctions(source, props);
15668
15669       if (options == null &&
15670           !(isObject(source) && (methodNames.length || !props.length))) {
15671         options = source;
15672         source = object;
15673         object = this;
15674         methodNames = baseFunctions(source, keys(source));
15675       }
15676       var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
15677           isFunc = isFunction(object);
15678
15679       arrayEach(methodNames, function(methodName) {
15680         var func = source[methodName];
15681         object[methodName] = func;
15682         if (isFunc) {
15683           object.prototype[methodName] = function() {
15684             var chainAll = this.__chain__;
15685             if (chain || chainAll) {
15686               var result = object(this.__wrapped__),
15687                   actions = result.__actions__ = copyArray(this.__actions__);
15688
15689               actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
15690               result.__chain__ = chainAll;
15691               return result;
15692             }
15693             return func.apply(object, arrayPush([this.value()], arguments));
15694           };
15695         }
15696       });
15697
15698       return object;
15699     }
15700
15701     /**
15702      * Reverts the `_` variable to its previous value and returns a reference to
15703      * the `lodash` function.
15704      *
15705      * @static
15706      * @since 0.1.0
15707      * @memberOf _
15708      * @category Util
15709      * @returns {Function} Returns the `lodash` function.
15710      * @example
15711      *
15712      * var lodash = _.noConflict();
15713      */
15714     function noConflict() {
15715       if (root._ === this) {
15716         root._ = oldDash;
15717       }
15718       return this;
15719     }
15720
15721     /**
15722      * This method returns `undefined`.
15723      *
15724      * @static
15725      * @memberOf _
15726      * @since 2.3.0
15727      * @category Util
15728      * @example
15729      *
15730      * _.times(2, _.noop);
15731      * // => [undefined, undefined]
15732      */
15733     function noop() {
15734       // No operation performed.
15735     }
15736
15737     /**
15738      * Creates a function that gets the argument at index `n`. If `n` is negative,
15739      * the nth argument from the end is returned.
15740      *
15741      * @static
15742      * @memberOf _
15743      * @since 4.0.0
15744      * @category Util
15745      * @param {number} [n=0] The index of the argument to return.
15746      * @returns {Function} Returns the new pass-thru function.
15747      * @example
15748      *
15749      * var func = _.nthArg(1);
15750      * func('a', 'b', 'c', 'd');
15751      * // => 'b'
15752      *
15753      * var func = _.nthArg(-2);
15754      * func('a', 'b', 'c', 'd');
15755      * // => 'c'
15756      */
15757     function nthArg(n) {
15758       n = toInteger(n);
15759       return baseRest(function(args) {
15760         return baseNth(args, n);
15761       });
15762     }
15763
15764     /**
15765      * Creates a function that invokes `iteratees` with the arguments it receives
15766      * and returns their results.
15767      *
15768      * @static
15769      * @memberOf _
15770      * @since 4.0.0
15771      * @category Util
15772      * @param {...(Function|Function[])} [iteratees=[_.identity]]
15773      *  The iteratees to invoke.
15774      * @returns {Function} Returns the new function.
15775      * @example
15776      *
15777      * var func = _.over([Math.max, Math.min]);
15778      *
15779      * func(1, 2, 3, 4);
15780      * // => [4, 1]
15781      */
15782     var over = createOver(arrayMap);
15783
15784     /**
15785      * Creates a function that checks if **all** of the `predicates` return
15786      * truthy when invoked with the arguments it receives.
15787      *
15788      * @static
15789      * @memberOf _
15790      * @since 4.0.0
15791      * @category Util
15792      * @param {...(Function|Function[])} [predicates=[_.identity]]
15793      *  The predicates to check.
15794      * @returns {Function} Returns the new function.
15795      * @example
15796      *
15797      * var func = _.overEvery([Boolean, isFinite]);
15798      *
15799      * func('1');
15800      * // => true
15801      *
15802      * func(null);
15803      * // => false
15804      *
15805      * func(NaN);
15806      * // => false
15807      */
15808     var overEvery = createOver(arrayEvery);
15809
15810     /**
15811      * Creates a function that checks if **any** of the `predicates` return
15812      * truthy when invoked with the arguments it receives.
15813      *
15814      * @static
15815      * @memberOf _
15816      * @since 4.0.0
15817      * @category Util
15818      * @param {...(Function|Function[])} [predicates=[_.identity]]
15819      *  The predicates to check.
15820      * @returns {Function} Returns the new function.
15821      * @example
15822      *
15823      * var func = _.overSome([Boolean, isFinite]);
15824      *
15825      * func('1');
15826      * // => true
15827      *
15828      * func(null);
15829      * // => true
15830      *
15831      * func(NaN);
15832      * // => false
15833      */
15834     var overSome = createOver(arraySome);
15835
15836     /**
15837      * Creates a function that returns the value at `path` of a given object.
15838      *
15839      * @static
15840      * @memberOf _
15841      * @since 2.4.0
15842      * @category Util
15843      * @param {Array|string} path The path of the property to get.
15844      * @returns {Function} Returns the new accessor function.
15845      * @example
15846      *
15847      * var objects = [
15848      *   { 'a': { 'b': 2 } },
15849      *   { 'a': { 'b': 1 } }
15850      * ];
15851      *
15852      * _.map(objects, _.property('a.b'));
15853      * // => [2, 1]
15854      *
15855      * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
15856      * // => [1, 2]
15857      */
15858     function property(path) {
15859       return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
15860     }
15861
15862     /**
15863      * The opposite of `_.property`; this method creates a function that returns
15864      * the value at a given path of `object`.
15865      *
15866      * @static
15867      * @memberOf _
15868      * @since 3.0.0
15869      * @category Util
15870      * @param {Object} object The object to query.
15871      * @returns {Function} Returns the new accessor function.
15872      * @example
15873      *
15874      * var array = [0, 1, 2],
15875      *     object = { 'a': array, 'b': array, 'c': array };
15876      *
15877      * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
15878      * // => [2, 0]
15879      *
15880      * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
15881      * // => [2, 0]
15882      */
15883     function propertyOf(object) {
15884       return function(path) {
15885         return object == null ? undefined : baseGet(object, path);
15886       };
15887     }
15888
15889     /**
15890      * Creates an array of numbers (positive and/or negative) progressing from
15891      * `start` up to, but not including, `end`. A step of `-1` is used if a negative
15892      * `start` is specified without an `end` or `step`. If `end` is not specified,
15893      * it's set to `start` with `start` then set to `0`.
15894      *
15895      * **Note:** JavaScript follows the IEEE-754 standard for resolving
15896      * floating-point values which can produce unexpected results.
15897      *
15898      * @static
15899      * @since 0.1.0
15900      * @memberOf _
15901      * @category Util
15902      * @param {number} [start=0] The start of the range.
15903      * @param {number} end The end of the range.
15904      * @param {number} [step=1] The value to increment or decrement by.
15905      * @returns {Array} Returns the range of numbers.
15906      * @see _.inRange, _.rangeRight
15907      * @example
15908      *
15909      * _.range(4);
15910      * // => [0, 1, 2, 3]
15911      *
15912      * _.range(-4);
15913      * // => [0, -1, -2, -3]
15914      *
15915      * _.range(1, 5);
15916      * // => [1, 2, 3, 4]
15917      *
15918      * _.range(0, 20, 5);
15919      * // => [0, 5, 10, 15]
15920      *
15921      * _.range(0, -4, -1);
15922      * // => [0, -1, -2, -3]
15923      *
15924      * _.range(1, 4, 0);
15925      * // => [1, 1, 1]
15926      *
15927      * _.range(0);
15928      * // => []
15929      */
15930     var range = createRange();
15931
15932     /**
15933      * This method is like `_.range` except that it populates values in
15934      * descending order.
15935      *
15936      * @static
15937      * @memberOf _
15938      * @since 4.0.0
15939      * @category Util
15940      * @param {number} [start=0] The start of the range.
15941      * @param {number} end The end of the range.
15942      * @param {number} [step=1] The value to increment or decrement by.
15943      * @returns {Array} Returns the range of numbers.
15944      * @see _.inRange, _.range
15945      * @example
15946      *
15947      * _.rangeRight(4);
15948      * // => [3, 2, 1, 0]
15949      *
15950      * _.rangeRight(-4);
15951      * // => [-3, -2, -1, 0]
15952      *
15953      * _.rangeRight(1, 5);
15954      * // => [4, 3, 2, 1]
15955      *
15956      * _.rangeRight(0, 20, 5);
15957      * // => [15, 10, 5, 0]
15958      *
15959      * _.rangeRight(0, -4, -1);
15960      * // => [-3, -2, -1, 0]
15961      *
15962      * _.rangeRight(1, 4, 0);
15963      * // => [1, 1, 1]
15964      *
15965      * _.rangeRight(0);
15966      * // => []
15967      */
15968     var rangeRight = createRange(true);
15969
15970     /**
15971      * This method returns a new empty array.
15972      *
15973      * @static
15974      * @memberOf _
15975      * @since 4.13.0
15976      * @category Util
15977      * @returns {Array} Returns the new empty array.
15978      * @example
15979      *
15980      * var arrays = _.times(2, _.stubArray);
15981      *
15982      * console.log(arrays);
15983      * // => [[], []]
15984      *
15985      * console.log(arrays[0] === arrays[1]);
15986      * // => false
15987      */
15988     function stubArray() {
15989       return [];
15990     }
15991
15992     /**
15993      * This method returns `false`.
15994      *
15995      * @static
15996      * @memberOf _
15997      * @since 4.13.0
15998      * @category Util
15999      * @returns {boolean} Returns `false`.
16000      * @example
16001      *
16002      * _.times(2, _.stubFalse);
16003      * // => [false, false]
16004      */
16005     function stubFalse() {
16006       return false;
16007     }
16008
16009     /**
16010      * This method returns a new empty object.
16011      *
16012      * @static
16013      * @memberOf _
16014      * @since 4.13.0
16015      * @category Util
16016      * @returns {Object} Returns the new empty object.
16017      * @example
16018      *
16019      * var objects = _.times(2, _.stubObject);
16020      *
16021      * console.log(objects);
16022      * // => [{}, {}]
16023      *
16024      * console.log(objects[0] === objects[1]);
16025      * // => false
16026      */
16027     function stubObject() {
16028       return {};
16029     }
16030
16031     /**
16032      * This method returns an empty string.
16033      *
16034      * @static
16035      * @memberOf _
16036      * @since 4.13.0
16037      * @category Util
16038      * @returns {string} Returns the empty string.
16039      * @example
16040      *
16041      * _.times(2, _.stubString);
16042      * // => ['', '']
16043      */
16044     function stubString() {
16045       return '';
16046     }
16047
16048     /**
16049      * This method returns `true`.
16050      *
16051      * @static
16052      * @memberOf _
16053      * @since 4.13.0
16054      * @category Util
16055      * @returns {boolean} Returns `true`.
16056      * @example
16057      *
16058      * _.times(2, _.stubTrue);
16059      * // => [true, true]
16060      */
16061     function stubTrue() {
16062       return true;
16063     }
16064
16065     /**
16066      * Invokes the iteratee `n` times, returning an array of the results of
16067      * each invocation. The iteratee is invoked with one argument; (index).
16068      *
16069      * @static
16070      * @since 0.1.0
16071      * @memberOf _
16072      * @category Util
16073      * @param {number} n The number of times to invoke `iteratee`.
16074      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
16075      * @returns {Array} Returns the array of results.
16076      * @example
16077      *
16078      * _.times(3, String);
16079      * // => ['0', '1', '2']
16080      *
16081      *  _.times(4, _.constant(0));
16082      * // => [0, 0, 0, 0]
16083      */
16084     function times(n, iteratee) {
16085       n = toInteger(n);
16086       if (n < 1 || n > MAX_SAFE_INTEGER) {
16087         return [];
16088       }
16089       var index = MAX_ARRAY_LENGTH,
16090           length = nativeMin(n, MAX_ARRAY_LENGTH);
16091
16092       iteratee = getIteratee(iteratee);
16093       n -= MAX_ARRAY_LENGTH;
16094
16095       var result = baseTimes(length, iteratee);
16096       while (++index < n) {
16097         iteratee(index);
16098       }
16099       return result;
16100     }
16101
16102     /**
16103      * Converts `value` to a property path array.
16104      *
16105      * @static
16106      * @memberOf _
16107      * @since 4.0.0
16108      * @category Util
16109      * @param {*} value The value to convert.
16110      * @returns {Array} Returns the new property path array.
16111      * @example
16112      *
16113      * _.toPath('a.b.c');
16114      * // => ['a', 'b', 'c']
16115      *
16116      * _.toPath('a[0].b.c');
16117      * // => ['a', '0', 'b', 'c']
16118      */
16119     function toPath(value) {
16120       if (isArray(value)) {
16121         return arrayMap(value, toKey);
16122       }
16123       return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
16124     }
16125
16126     /**
16127      * Generates a unique ID. If `prefix` is given, the ID is appended to it.
16128      *
16129      * @static
16130      * @since 0.1.0
16131      * @memberOf _
16132      * @category Util
16133      * @param {string} [prefix=''] The value to prefix the ID with.
16134      * @returns {string} Returns the unique ID.
16135      * @example
16136      *
16137      * _.uniqueId('contact_');
16138      * // => 'contact_104'
16139      *
16140      * _.uniqueId();
16141      * // => '105'
16142      */
16143     function uniqueId(prefix) {
16144       var id = ++idCounter;
16145       return toString(prefix) + id;
16146     }
16147
16148     /*------------------------------------------------------------------------*/
16149
16150     /**
16151      * Adds two numbers.
16152      *
16153      * @static
16154      * @memberOf _
16155      * @since 3.4.0
16156      * @category Math
16157      * @param {number} augend The first number in an addition.
16158      * @param {number} addend The second number in an addition.
16159      * @returns {number} Returns the total.
16160      * @example
16161      *
16162      * _.add(6, 4);
16163      * // => 10
16164      */
16165     var add = createMathOperation(function(augend, addend) {
16166       return augend + addend;
16167     }, 0);
16168
16169     /**
16170      * Computes `number` rounded up to `precision`.
16171      *
16172      * @static
16173      * @memberOf _
16174      * @since 3.10.0
16175      * @category Math
16176      * @param {number} number The number to round up.
16177      * @param {number} [precision=0] The precision to round up to.
16178      * @returns {number} Returns the rounded up number.
16179      * @example
16180      *
16181      * _.ceil(4.006);
16182      * // => 5
16183      *
16184      * _.ceil(6.004, 2);
16185      * // => 6.01
16186      *
16187      * _.ceil(6040, -2);
16188      * // => 6100
16189      */
16190     var ceil = createRound('ceil');
16191
16192     /**
16193      * Divide two numbers.
16194      *
16195      * @static
16196      * @memberOf _
16197      * @since 4.7.0
16198      * @category Math
16199      * @param {number} dividend The first number in a division.
16200      * @param {number} divisor The second number in a division.
16201      * @returns {number} Returns the quotient.
16202      * @example
16203      *
16204      * _.divide(6, 4);
16205      * // => 1.5
16206      */
16207     var divide = createMathOperation(function(dividend, divisor) {
16208       return dividend / divisor;
16209     }, 1);
16210
16211     /**
16212      * Computes `number` rounded down to `precision`.
16213      *
16214      * @static
16215      * @memberOf _
16216      * @since 3.10.0
16217      * @category Math
16218      * @param {number} number The number to round down.
16219      * @param {number} [precision=0] The precision to round down to.
16220      * @returns {number} Returns the rounded down number.
16221      * @example
16222      *
16223      * _.floor(4.006);
16224      * // => 4
16225      *
16226      * _.floor(0.046, 2);
16227      * // => 0.04
16228      *
16229      * _.floor(4060, -2);
16230      * // => 4000
16231      */
16232     var floor = createRound('floor');
16233
16234     /**
16235      * Computes the maximum value of `array`. If `array` is empty or falsey,
16236      * `undefined` is returned.
16237      *
16238      * @static
16239      * @since 0.1.0
16240      * @memberOf _
16241      * @category Math
16242      * @param {Array} array The array to iterate over.
16243      * @returns {*} Returns the maximum value.
16244      * @example
16245      *
16246      * _.max([4, 2, 8, 6]);
16247      * // => 8
16248      *
16249      * _.max([]);
16250      * // => undefined
16251      */
16252     function max(array) {
16253       return (array && array.length)
16254         ? baseExtremum(array, identity, baseGt)
16255         : undefined;
16256     }
16257
16258     /**
16259      * This method is like `_.max` except that it accepts `iteratee` which is
16260      * invoked for each element in `array` to generate the criterion by which
16261      * the value is ranked. The iteratee is invoked with one argument: (value).
16262      *
16263      * @static
16264      * @memberOf _
16265      * @since 4.0.0
16266      * @category Math
16267      * @param {Array} array The array to iterate over.
16268      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16269      * @returns {*} Returns the maximum value.
16270      * @example
16271      *
16272      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16273      *
16274      * _.maxBy(objects, function(o) { return o.n; });
16275      * // => { 'n': 2 }
16276      *
16277      * // The `_.property` iteratee shorthand.
16278      * _.maxBy(objects, 'n');
16279      * // => { 'n': 2 }
16280      */
16281     function maxBy(array, iteratee) {
16282       return (array && array.length)
16283         ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
16284         : undefined;
16285     }
16286
16287     /**
16288      * Computes the mean of the values in `array`.
16289      *
16290      * @static
16291      * @memberOf _
16292      * @since 4.0.0
16293      * @category Math
16294      * @param {Array} array The array to iterate over.
16295      * @returns {number} Returns the mean.
16296      * @example
16297      *
16298      * _.mean([4, 2, 8, 6]);
16299      * // => 5
16300      */
16301     function mean(array) {
16302       return baseMean(array, identity);
16303     }
16304
16305     /**
16306      * This method is like `_.mean` except that it accepts `iteratee` which is
16307      * invoked for each element in `array` to generate the value to be averaged.
16308      * The iteratee is invoked with one argument: (value).
16309      *
16310      * @static
16311      * @memberOf _
16312      * @since 4.7.0
16313      * @category Math
16314      * @param {Array} array The array to iterate over.
16315      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16316      * @returns {number} Returns the mean.
16317      * @example
16318      *
16319      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16320      *
16321      * _.meanBy(objects, function(o) { return o.n; });
16322      * // => 5
16323      *
16324      * // The `_.property` iteratee shorthand.
16325      * _.meanBy(objects, 'n');
16326      * // => 5
16327      */
16328     function meanBy(array, iteratee) {
16329       return baseMean(array, getIteratee(iteratee, 2));
16330     }
16331
16332     /**
16333      * Computes the minimum value of `array`. If `array` is empty or falsey,
16334      * `undefined` is returned.
16335      *
16336      * @static
16337      * @since 0.1.0
16338      * @memberOf _
16339      * @category Math
16340      * @param {Array} array The array to iterate over.
16341      * @returns {*} Returns the minimum value.
16342      * @example
16343      *
16344      * _.min([4, 2, 8, 6]);
16345      * // => 2
16346      *
16347      * _.min([]);
16348      * // => undefined
16349      */
16350     function min(array) {
16351       return (array && array.length)
16352         ? baseExtremum(array, identity, baseLt)
16353         : undefined;
16354     }
16355
16356     /**
16357      * This method is like `_.min` except that it accepts `iteratee` which is
16358      * invoked for each element in `array` to generate the criterion by which
16359      * the value is ranked. The iteratee is invoked with one argument: (value).
16360      *
16361      * @static
16362      * @memberOf _
16363      * @since 4.0.0
16364      * @category Math
16365      * @param {Array} array The array to iterate over.
16366      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16367      * @returns {*} Returns the minimum value.
16368      * @example
16369      *
16370      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16371      *
16372      * _.minBy(objects, function(o) { return o.n; });
16373      * // => { 'n': 1 }
16374      *
16375      * // The `_.property` iteratee shorthand.
16376      * _.minBy(objects, 'n');
16377      * // => { 'n': 1 }
16378      */
16379     function minBy(array, iteratee) {
16380       return (array && array.length)
16381         ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
16382         : undefined;
16383     }
16384
16385     /**
16386      * Multiply two numbers.
16387      *
16388      * @static
16389      * @memberOf _
16390      * @since 4.7.0
16391      * @category Math
16392      * @param {number} multiplier The first number in a multiplication.
16393      * @param {number} multiplicand The second number in a multiplication.
16394      * @returns {number} Returns the product.
16395      * @example
16396      *
16397      * _.multiply(6, 4);
16398      * // => 24
16399      */
16400     var multiply = createMathOperation(function(multiplier, multiplicand) {
16401       return multiplier * multiplicand;
16402     }, 1);
16403
16404     /**
16405      * Computes `number` rounded to `precision`.
16406      *
16407      * @static
16408      * @memberOf _
16409      * @since 3.10.0
16410      * @category Math
16411      * @param {number} number The number to round.
16412      * @param {number} [precision=0] The precision to round to.
16413      * @returns {number} Returns the rounded number.
16414      * @example
16415      *
16416      * _.round(4.006);
16417      * // => 4
16418      *
16419      * _.round(4.006, 2);
16420      * // => 4.01
16421      *
16422      * _.round(4060, -2);
16423      * // => 4100
16424      */
16425     var round = createRound('round');
16426
16427     /**
16428      * Subtract two numbers.
16429      *
16430      * @static
16431      * @memberOf _
16432      * @since 4.0.0
16433      * @category Math
16434      * @param {number} minuend The first number in a subtraction.
16435      * @param {number} subtrahend The second number in a subtraction.
16436      * @returns {number} Returns the difference.
16437      * @example
16438      *
16439      * _.subtract(6, 4);
16440      * // => 2
16441      */
16442     var subtract = createMathOperation(function(minuend, subtrahend) {
16443       return minuend - subtrahend;
16444     }, 0);
16445
16446     /**
16447      * Computes the sum of the values in `array`.
16448      *
16449      * @static
16450      * @memberOf _
16451      * @since 3.4.0
16452      * @category Math
16453      * @param {Array} array The array to iterate over.
16454      * @returns {number} Returns the sum.
16455      * @example
16456      *
16457      * _.sum([4, 2, 8, 6]);
16458      * // => 20
16459      */
16460     function sum(array) {
16461       return (array && array.length)
16462         ? baseSum(array, identity)
16463         : 0;
16464     }
16465
16466     /**
16467      * This method is like `_.sum` except that it accepts `iteratee` which is
16468      * invoked for each element in `array` to generate the value to be summed.
16469      * The iteratee is invoked with one argument: (value).
16470      *
16471      * @static
16472      * @memberOf _
16473      * @since 4.0.0
16474      * @category Math
16475      * @param {Array} array The array to iterate over.
16476      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16477      * @returns {number} Returns the sum.
16478      * @example
16479      *
16480      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16481      *
16482      * _.sumBy(objects, function(o) { return o.n; });
16483      * // => 20
16484      *
16485      * // The `_.property` iteratee shorthand.
16486      * _.sumBy(objects, 'n');
16487      * // => 20
16488      */
16489     function sumBy(array, iteratee) {
16490       return (array && array.length)
16491         ? baseSum(array, getIteratee(iteratee, 2))
16492         : 0;
16493     }
16494
16495     /*------------------------------------------------------------------------*/
16496
16497     // Add methods that return wrapped values in chain sequences.
16498     lodash.after = after;
16499     lodash.ary = ary;
16500     lodash.assign = assign;
16501     lodash.assignIn = assignIn;
16502     lodash.assignInWith = assignInWith;
16503     lodash.assignWith = assignWith;
16504     lodash.at = at;
16505     lodash.before = before;
16506     lodash.bind = bind;
16507     lodash.bindAll = bindAll;
16508     lodash.bindKey = bindKey;
16509     lodash.castArray = castArray;
16510     lodash.chain = chain;
16511     lodash.chunk = chunk;
16512     lodash.compact = compact;
16513     lodash.concat = concat;
16514     lodash.cond = cond;
16515     lodash.conforms = conforms;
16516     lodash.constant = constant;
16517     lodash.countBy = countBy;
16518     lodash.create = create;
16519     lodash.curry = curry;
16520     lodash.curryRight = curryRight;
16521     lodash.debounce = debounce;
16522     lodash.defaults = defaults;
16523     lodash.defaultsDeep = defaultsDeep;
16524     lodash.defer = defer;
16525     lodash.delay = delay;
16526     lodash.difference = difference;
16527     lodash.differenceBy = differenceBy;
16528     lodash.differenceWith = differenceWith;
16529     lodash.drop = drop;
16530     lodash.dropRight = dropRight;
16531     lodash.dropRightWhile = dropRightWhile;
16532     lodash.dropWhile = dropWhile;
16533     lodash.fill = fill;
16534     lodash.filter = filter;
16535     lodash.flatMap = flatMap;
16536     lodash.flatMapDeep = flatMapDeep;
16537     lodash.flatMapDepth = flatMapDepth;
16538     lodash.flatten = flatten;
16539     lodash.flattenDeep = flattenDeep;
16540     lodash.flattenDepth = flattenDepth;
16541     lodash.flip = flip;
16542     lodash.flow = flow;
16543     lodash.flowRight = flowRight;
16544     lodash.fromPairs = fromPairs;
16545     lodash.functions = functions;
16546     lodash.functionsIn = functionsIn;
16547     lodash.groupBy = groupBy;
16548     lodash.initial = initial;
16549     lodash.intersection = intersection;
16550     lodash.intersectionBy = intersectionBy;
16551     lodash.intersectionWith = intersectionWith;
16552     lodash.invert = invert;
16553     lodash.invertBy = invertBy;
16554     lodash.invokeMap = invokeMap;
16555     lodash.iteratee = iteratee;
16556     lodash.keyBy = keyBy;
16557     lodash.keys = keys;
16558     lodash.keysIn = keysIn;
16559     lodash.map = map;
16560     lodash.mapKeys = mapKeys;
16561     lodash.mapValues = mapValues;
16562     lodash.matches = matches;
16563     lodash.matchesProperty = matchesProperty;
16564     lodash.memoize = memoize;
16565     lodash.merge = merge;
16566     lodash.mergeWith = mergeWith;
16567     lodash.method = method;
16568     lodash.methodOf = methodOf;
16569     lodash.mixin = mixin;
16570     lodash.negate = negate;
16571     lodash.nthArg = nthArg;
16572     lodash.omit = omit;
16573     lodash.omitBy = omitBy;
16574     lodash.once = once;
16575     lodash.orderBy = orderBy;
16576     lodash.over = over;
16577     lodash.overArgs = overArgs;
16578     lodash.overEvery = overEvery;
16579     lodash.overSome = overSome;
16580     lodash.partial = partial;
16581     lodash.partialRight = partialRight;
16582     lodash.partition = partition;
16583     lodash.pick = pick;
16584     lodash.pickBy = pickBy;
16585     lodash.property = property;
16586     lodash.propertyOf = propertyOf;
16587     lodash.pull = pull;
16588     lodash.pullAll = pullAll;
16589     lodash.pullAllBy = pullAllBy;
16590     lodash.pullAllWith = pullAllWith;
16591     lodash.pullAt = pullAt;
16592     lodash.range = range;
16593     lodash.rangeRight = rangeRight;
16594     lodash.rearg = rearg;
16595     lodash.reject = reject;
16596     lodash.remove = remove;
16597     lodash.rest = rest;
16598     lodash.reverse = reverse;
16599     lodash.sampleSize = sampleSize;
16600     lodash.set = set;
16601     lodash.setWith = setWith;
16602     lodash.shuffle = shuffle;
16603     lodash.slice = slice;
16604     lodash.sortBy = sortBy;
16605     lodash.sortedUniq = sortedUniq;
16606     lodash.sortedUniqBy = sortedUniqBy;
16607     lodash.split = split;
16608     lodash.spread = spread;
16609     lodash.tail = tail;
16610     lodash.take = take;
16611     lodash.takeRight = takeRight;
16612     lodash.takeRightWhile = takeRightWhile;
16613     lodash.takeWhile = takeWhile;
16614     lodash.tap = tap;
16615     lodash.throttle = throttle;
16616     lodash.thru = thru;
16617     lodash.toArray = toArray;
16618     lodash.toPairs = toPairs;
16619     lodash.toPairsIn = toPairsIn;
16620     lodash.toPath = toPath;
16621     lodash.toPlainObject = toPlainObject;
16622     lodash.transform = transform;
16623     lodash.unary = unary;
16624     lodash.union = union;
16625     lodash.unionBy = unionBy;
16626     lodash.unionWith = unionWith;
16627     lodash.uniq = uniq;
16628     lodash.uniqBy = uniqBy;
16629     lodash.uniqWith = uniqWith;
16630     lodash.unset = unset;
16631     lodash.unzip = unzip;
16632     lodash.unzipWith = unzipWith;
16633     lodash.update = update;
16634     lodash.updateWith = updateWith;
16635     lodash.values = values;
16636     lodash.valuesIn = valuesIn;
16637     lodash.without = without;
16638     lodash.words = words;
16639     lodash.wrap = wrap;
16640     lodash.xor = xor;
16641     lodash.xorBy = xorBy;
16642     lodash.xorWith = xorWith;
16643     lodash.zip = zip;
16644     lodash.zipObject = zipObject;
16645     lodash.zipObjectDeep = zipObjectDeep;
16646     lodash.zipWith = zipWith;
16647
16648     // Add aliases.
16649     lodash.entries = toPairs;
16650     lodash.entriesIn = toPairsIn;
16651     lodash.extend = assignIn;
16652     lodash.extendWith = assignInWith;
16653
16654     // Add methods to `lodash.prototype`.
16655     mixin(lodash, lodash);
16656
16657     /*------------------------------------------------------------------------*/
16658
16659     // Add methods that return unwrapped values in chain sequences.
16660     lodash.add = add;
16661     lodash.attempt = attempt;
16662     lodash.camelCase = camelCase;
16663     lodash.capitalize = capitalize;
16664     lodash.ceil = ceil;
16665     lodash.clamp = clamp;
16666     lodash.clone = clone;
16667     lodash.cloneDeep = cloneDeep;
16668     lodash.cloneDeepWith = cloneDeepWith;
16669     lodash.cloneWith = cloneWith;
16670     lodash.conformsTo = conformsTo;
16671     lodash.deburr = deburr;
16672     lodash.defaultTo = defaultTo;
16673     lodash.divide = divide;
16674     lodash.endsWith = endsWith;
16675     lodash.eq = eq;
16676     lodash.escape = escape;
16677     lodash.escapeRegExp = escapeRegExp;
16678     lodash.every = every;
16679     lodash.find = find;
16680     lodash.findIndex = findIndex;
16681     lodash.findKey = findKey;
16682     lodash.findLast = findLast;
16683     lodash.findLastIndex = findLastIndex;
16684     lodash.findLastKey = findLastKey;
16685     lodash.floor = floor;
16686     lodash.forEach = forEach;
16687     lodash.forEachRight = forEachRight;
16688     lodash.forIn = forIn;
16689     lodash.forInRight = forInRight;
16690     lodash.forOwn = forOwn;
16691     lodash.forOwnRight = forOwnRight;
16692     lodash.get = get;
16693     lodash.gt = gt;
16694     lodash.gte = gte;
16695     lodash.has = has;
16696     lodash.hasIn = hasIn;
16697     lodash.head = head;
16698     lodash.identity = identity;
16699     lodash.includes = includes;
16700     lodash.indexOf = indexOf;
16701     lodash.inRange = inRange;
16702     lodash.invoke = invoke;
16703     lodash.isArguments = isArguments;
16704     lodash.isArray = isArray;
16705     lodash.isArrayBuffer = isArrayBuffer;
16706     lodash.isArrayLike = isArrayLike;
16707     lodash.isArrayLikeObject = isArrayLikeObject;
16708     lodash.isBoolean = isBoolean;
16709     lodash.isBuffer = isBuffer;
16710     lodash.isDate = isDate;
16711     lodash.isElement = isElement;
16712     lodash.isEmpty = isEmpty;
16713     lodash.isEqual = isEqual;
16714     lodash.isEqualWith = isEqualWith;
16715     lodash.isError = isError;
16716     lodash.isFinite = isFinite;
16717     lodash.isFunction = isFunction;
16718     lodash.isInteger = isInteger;
16719     lodash.isLength = isLength;
16720     lodash.isMap = isMap;
16721     lodash.isMatch = isMatch;
16722     lodash.isMatchWith = isMatchWith;
16723     lodash.isNaN = isNaN;
16724     lodash.isNative = isNative;
16725     lodash.isNil = isNil;
16726     lodash.isNull = isNull;
16727     lodash.isNumber = isNumber;
16728     lodash.isObject = isObject;
16729     lodash.isObjectLike = isObjectLike;
16730     lodash.isPlainObject = isPlainObject;
16731     lodash.isRegExp = isRegExp;
16732     lodash.isSafeInteger = isSafeInteger;
16733     lodash.isSet = isSet;
16734     lodash.isString = isString;
16735     lodash.isSymbol = isSymbol;
16736     lodash.isTypedArray = isTypedArray;
16737     lodash.isUndefined = isUndefined;
16738     lodash.isWeakMap = isWeakMap;
16739     lodash.isWeakSet = isWeakSet;
16740     lodash.join = join;
16741     lodash.kebabCase = kebabCase;
16742     lodash.last = last;
16743     lodash.lastIndexOf = lastIndexOf;
16744     lodash.lowerCase = lowerCase;
16745     lodash.lowerFirst = lowerFirst;
16746     lodash.lt = lt;
16747     lodash.lte = lte;
16748     lodash.max = max;
16749     lodash.maxBy = maxBy;
16750     lodash.mean = mean;
16751     lodash.meanBy = meanBy;
16752     lodash.min = min;
16753     lodash.minBy = minBy;
16754     lodash.stubArray = stubArray;
16755     lodash.stubFalse = stubFalse;
16756     lodash.stubObject = stubObject;
16757     lodash.stubString = stubString;
16758     lodash.stubTrue = stubTrue;
16759     lodash.multiply = multiply;
16760     lodash.nth = nth;
16761     lodash.noConflict = noConflict;
16762     lodash.noop = noop;
16763     lodash.now = now;
16764     lodash.pad = pad;
16765     lodash.padEnd = padEnd;
16766     lodash.padStart = padStart;
16767     lodash.parseInt = parseInt;
16768     lodash.random = random;
16769     lodash.reduce = reduce;
16770     lodash.reduceRight = reduceRight;
16771     lodash.repeat = repeat;
16772     lodash.replace = replace;
16773     lodash.result = result;
16774     lodash.round = round;
16775     lodash.runInContext = runInContext;
16776     lodash.sample = sample;
16777     lodash.size = size;
16778     lodash.snakeCase = snakeCase;
16779     lodash.some = some;
16780     lodash.sortedIndex = sortedIndex;
16781     lodash.sortedIndexBy = sortedIndexBy;
16782     lodash.sortedIndexOf = sortedIndexOf;
16783     lodash.sortedLastIndex = sortedLastIndex;
16784     lodash.sortedLastIndexBy = sortedLastIndexBy;
16785     lodash.sortedLastIndexOf = sortedLastIndexOf;
16786     lodash.startCase = startCase;
16787     lodash.startsWith = startsWith;
16788     lodash.subtract = subtract;
16789     lodash.sum = sum;
16790     lodash.sumBy = sumBy;
16791     lodash.template = template;
16792     lodash.times = times;
16793     lodash.toFinite = toFinite;
16794     lodash.toInteger = toInteger;
16795     lodash.toLength = toLength;
16796     lodash.toLower = toLower;
16797     lodash.toNumber = toNumber;
16798     lodash.toSafeInteger = toSafeInteger;
16799     lodash.toString = toString;
16800     lodash.toUpper = toUpper;
16801     lodash.trim = trim;
16802     lodash.trimEnd = trimEnd;
16803     lodash.trimStart = trimStart;
16804     lodash.truncate = truncate;
16805     lodash.unescape = unescape;
16806     lodash.uniqueId = uniqueId;
16807     lodash.upperCase = upperCase;
16808     lodash.upperFirst = upperFirst;
16809
16810     // Add aliases.
16811     lodash.each = forEach;
16812     lodash.eachRight = forEachRight;
16813     lodash.first = head;
16814
16815     mixin(lodash, (function() {
16816       var source = {};
16817       baseForOwn(lodash, function(func, methodName) {
16818         if (!hasOwnProperty.call(lodash.prototype, methodName)) {
16819           source[methodName] = func;
16820         }
16821       });
16822       return source;
16823     }()), { 'chain': false });
16824
16825     /*------------------------------------------------------------------------*/
16826
16827     /**
16828      * The semantic version number.
16829      *
16830      * @static
16831      * @memberOf _
16832      * @type {string}
16833      */
16834     lodash.VERSION = VERSION;
16835
16836     // Assign default placeholders.
16837     arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
16838       lodash[methodName].placeholder = lodash;
16839     });
16840
16841     // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
16842     arrayEach(['drop', 'take'], function(methodName, index) {
16843       LazyWrapper.prototype[methodName] = function(n) {
16844         var filtered = this.__filtered__;
16845         if (filtered && !index) {
16846           return new LazyWrapper(this);
16847         }
16848         n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
16849
16850         var result = this.clone();
16851         if (filtered) {
16852           result.__takeCount__ = nativeMin(n, result.__takeCount__);
16853         } else {
16854           result.__views__.push({
16855             'size': nativeMin(n, MAX_ARRAY_LENGTH),
16856             'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
16857           });
16858         }
16859         return result;
16860       };
16861
16862       LazyWrapper.prototype[methodName + 'Right'] = function(n) {
16863         return this.reverse()[methodName](n).reverse();
16864       };
16865     });
16866
16867     // Add `LazyWrapper` methods that accept an `iteratee` value.
16868     arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
16869       var type = index + 1,
16870           isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
16871
16872       LazyWrapper.prototype[methodName] = function(iteratee) {
16873         var result = this.clone();
16874         result.__iteratees__.push({
16875           'iteratee': getIteratee(iteratee, 3),
16876           'type': type
16877         });
16878         result.__filtered__ = result.__filtered__ || isFilter;
16879         return result;
16880       };
16881     });
16882
16883     // Add `LazyWrapper` methods for `_.head` and `_.last`.
16884     arrayEach(['head', 'last'], function(methodName, index) {
16885       var takeName = 'take' + (index ? 'Right' : '');
16886
16887       LazyWrapper.prototype[methodName] = function() {
16888         return this[takeName](1).value()[0];
16889       };
16890     });
16891
16892     // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
16893     arrayEach(['initial', 'tail'], function(methodName, index) {
16894       var dropName = 'drop' + (index ? '' : 'Right');
16895
16896       LazyWrapper.prototype[methodName] = function() {
16897         return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
16898       };
16899     });
16900
16901     LazyWrapper.prototype.compact = function() {
16902       return this.filter(identity);
16903     };
16904
16905     LazyWrapper.prototype.find = function(predicate) {
16906       return this.filter(predicate).head();
16907     };
16908
16909     LazyWrapper.prototype.findLast = function(predicate) {
16910       return this.reverse().find(predicate);
16911     };
16912
16913     LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
16914       if (typeof path == 'function') {
16915         return new LazyWrapper(this);
16916       }
16917       return this.map(function(value) {
16918         return baseInvoke(value, path, args);
16919       });
16920     });
16921
16922     LazyWrapper.prototype.reject = function(predicate) {
16923       return this.filter(negate(getIteratee(predicate)));
16924     };
16925
16926     LazyWrapper.prototype.slice = function(start, end) {
16927       start = toInteger(start);
16928
16929       var result = this;
16930       if (result.__filtered__ && (start > 0 || end < 0)) {
16931         return new LazyWrapper(result);
16932       }
16933       if (start < 0) {
16934         result = result.takeRight(-start);
16935       } else if (start) {
16936         result = result.drop(start);
16937       }
16938       if (end !== undefined) {
16939         end = toInteger(end);
16940         result = end < 0 ? result.dropRight(-end) : result.take(end - start);
16941       }
16942       return result;
16943     };
16944
16945     LazyWrapper.prototype.takeRightWhile = function(predicate) {
16946       return this.reverse().takeWhile(predicate).reverse();
16947     };
16948
16949     LazyWrapper.prototype.toArray = function() {
16950       return this.take(MAX_ARRAY_LENGTH);
16951     };
16952
16953     // Add `LazyWrapper` methods to `lodash.prototype`.
16954     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
16955       var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
16956           isTaker = /^(?:head|last)$/.test(methodName),
16957           lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
16958           retUnwrapped = isTaker || /^find/.test(methodName);
16959
16960       if (!lodashFunc) {
16961         return;
16962       }
16963       lodash.prototype[methodName] = function() {
16964         var value = this.__wrapped__,
16965             args = isTaker ? [1] : arguments,
16966             isLazy = value instanceof LazyWrapper,
16967             iteratee = args[0],
16968             useLazy = isLazy || isArray(value);
16969
16970         var interceptor = function(value) {
16971           var result = lodashFunc.apply(lodash, arrayPush([value], args));
16972           return (isTaker && chainAll) ? result[0] : result;
16973         };
16974
16975         if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
16976           // Avoid lazy use if the iteratee has a "length" value other than `1`.
16977           isLazy = useLazy = false;
16978         }
16979         var chainAll = this.__chain__,
16980             isHybrid = !!this.__actions__.length,
16981             isUnwrapped = retUnwrapped && !chainAll,
16982             onlyLazy = isLazy && !isHybrid;
16983
16984         if (!retUnwrapped && useLazy) {
16985           value = onlyLazy ? value : new LazyWrapper(this);
16986           var result = func.apply(value, args);
16987           result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
16988           return new LodashWrapper(result, chainAll);
16989         }
16990         if (isUnwrapped && onlyLazy) {
16991           return func.apply(this, args);
16992         }
16993         result = this.thru(interceptor);
16994         return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
16995       };
16996     });
16997
16998     // Add `Array` methods to `lodash.prototype`.
16999     arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
17000       var func = arrayProto[methodName],
17001           chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
17002           retUnwrapped = /^(?:pop|shift)$/.test(methodName);
17003
17004       lodash.prototype[methodName] = function() {
17005         var args = arguments;
17006         if (retUnwrapped && !this.__chain__) {
17007           var value = this.value();
17008           return func.apply(isArray(value) ? value : [], args);
17009         }
17010         return this[chainName](function(value) {
17011           return func.apply(isArray(value) ? value : [], args);
17012         });
17013       };
17014     });
17015
17016     // Map minified method names to their real names.
17017     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
17018       var lodashFunc = lodash[methodName];
17019       if (lodashFunc) {
17020         var key = (lodashFunc.name + ''),
17021             names = realNames[key] || (realNames[key] = []);
17022
17023         names.push({ 'name': methodName, 'func': lodashFunc });
17024       }
17025     });
17026
17027     realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
17028       'name': 'wrapper',
17029       'func': undefined
17030     }];
17031
17032     // Add methods to `LazyWrapper`.
17033     LazyWrapper.prototype.clone = lazyClone;
17034     LazyWrapper.prototype.reverse = lazyReverse;
17035     LazyWrapper.prototype.value = lazyValue;
17036
17037     // Add chain sequence methods to the `lodash` wrapper.
17038     lodash.prototype.at = wrapperAt;
17039     lodash.prototype.chain = wrapperChain;
17040     lodash.prototype.commit = wrapperCommit;
17041     lodash.prototype.next = wrapperNext;
17042     lodash.prototype.plant = wrapperPlant;
17043     lodash.prototype.reverse = wrapperReverse;
17044     lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
17045
17046     // Add lazy aliases.
17047     lodash.prototype.first = lodash.prototype.head;
17048
17049     if (symIterator) {
17050       lodash.prototype[symIterator] = wrapperToIterator;
17051     }
17052     return lodash;
17053   });
17054
17055   /*--------------------------------------------------------------------------*/
17056
17057   // Export lodash.
17058   var _ = runInContext();
17059
17060   // Some AMD build optimizers, like r.js, check for condition patterns like:
17061   if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
17062     // Expose Lodash on the global object to prevent errors when Lodash is
17063     // loaded by a script tag in the presence of an AMD loader.
17064     // See http://requirejs.org/docs/errors.html#mismatch for more details.
17065     // Use `_.noConflict` to remove Lodash from the global object.
17066     root._ = _;
17067
17068     // Define as an anonymous module so, through path mapping, it can be
17069     // referenced as the "underscore" module.
17070     define(function() {
17071       return _;
17072     });
17073   }
17074   // Check for `exports` after `define` in case a build optimizer adds it.
17075   else if (freeModule) {
17076     // Export for Node.js.
17077     (freeModule.exports = _)._ = _;
17078     // Export for CommonJS support.
17079     freeExports._ = _;
17080   }
17081   else {
17082     // Export to the global object.
17083     root._ = _;
17084   }
17085 }.call(commonjsGlobal));
17086 });
17087
17088 function osmIsInterestingTag(key) {
17089     return key !== 'attribution' &&
17090         key !== 'created_by' &&
17091         key !== 'source' &&
17092         key !== 'odbl' &&
17093         key.indexOf('tiger:') !== 0;
17094
17095 }
17096
17097
17098 var osmOneWayTags = {
17099     'aerialway': {
17100         'chair_lift': true,
17101         'mixed_lift': true,
17102         't-bar': true,
17103         'j-bar': true,
17104         'platter': true,
17105         'rope_tow': true,
17106         'magic_carpet': true,
17107         'yes': true
17108     },
17109     'highway': {
17110         'motorway': true,
17111         'motorway_link': true
17112     },
17113     'junction': {
17114         'roundabout': true
17115     },
17116     'man_made': {
17117         'piste:halfpipe': true
17118     },
17119     'piste:type': {
17120         'downhill': true,
17121         'sled': true,
17122         'yes': true
17123     },
17124     'waterway': {
17125         'river': true,
17126         'stream': true
17127     }
17128 };
17129
17130
17131 var osmPavedTags = {
17132     'surface': {
17133         'paved': true,
17134         'asphalt': true,
17135         'concrete': true
17136     },
17137     'tracktype': {
17138         'grade1': true
17139     }
17140 };
17141
17142 var dataWikipedia = [
17143     [
17144         "Abkhazian",
17145         "Аҧсшәа",
17146         "ab"
17147     ],
17148     [
17149         "Achinese",
17150         "Acèh",
17151         "ace"
17152     ],
17153     [
17154         "Adyghe",
17155         "адыгабзэ",
17156         "ady"
17157     ],
17158     [
17159         "Afrikaans",
17160         "Afrikaans",
17161         "af"
17162     ],
17163     [
17164         "Akan",
17165         "Akan",
17166         "ak"
17167     ],
17168     [
17169         "Alemannisch",
17170         "Alemannisch",
17171         "als"
17172     ],
17173     [
17174         "Amharic",
17175         "አማርኛ",
17176         "am"
17177     ],
17178     [
17179         "Aragonese",
17180         "aragonés",
17181         "an"
17182     ],
17183     [
17184         "Old English",
17185         "Ænglisc",
17186         "ang"
17187     ],
17188     [
17189         "Arabic",
17190         "العربية",
17191         "ar"
17192     ],
17193     [
17194         "Aramaic",
17195         "ܐܪܡܝܐ",
17196         "arc"
17197     ],
17198     [
17199         "Egyptian Arabic",
17200         "مصرى",
17201         "arz"
17202     ],
17203     [
17204         "Assamese",
17205         "অসমীয়া",
17206         "as"
17207     ],
17208     [
17209         "Asturian",
17210         "asturianu",
17211         "ast"
17212     ],
17213     [
17214         "Avaric",
17215         "авар",
17216         "av"
17217     ],
17218     [
17219         "Aymara",
17220         "Aymar aru",
17221         "ay"
17222     ],
17223     [
17224         "Azerbaijani",
17225         "azərbaycanca",
17226         "az"
17227     ],
17228     [
17229         "تۆرکجه",
17230         "تۆرکجه",
17231         "azb"
17232     ],
17233     [
17234         "Bashkir",
17235         "башҡортса",
17236         "ba"
17237     ],
17238     [
17239         "Bavarian",
17240         "Boarisch",
17241         "bar"
17242     ],
17243     [
17244         "Samogitian",
17245         "žemaitėška",
17246         "bat-smg"
17247     ],
17248     [
17249         "Bikol Central",
17250         "Bikol Central",
17251         "bcl"
17252     ],
17253     [
17254         "Belarusian",
17255         "беларуская",
17256         "be"
17257     ],
17258     [
17259         "беларуская (тарашкевіца)‎",
17260         "беларуская (тарашкевіца)‎",
17261         "be-x-old"
17262     ],
17263     [
17264         "Bulgarian",
17265         "български",
17266         "bg"
17267     ],
17268     [
17269         "भोजपुरी",
17270         "भोजपुरी",
17271         "bh"
17272     ],
17273     [
17274         "Bislama",
17275         "Bislama",
17276         "bi"
17277     ],
17278     [
17279         "Banjar",
17280         "Bahasa Banjar",
17281         "bjn"
17282     ],
17283     [
17284         "Bambara",
17285         "bamanankan",
17286         "bm"
17287     ],
17288     [
17289         "Bengali",
17290         "বাংলা",
17291         "bn"
17292     ],
17293     [
17294         "Tibetan",
17295         "བོད་ཡིག",
17296         "bo"
17297     ],
17298     [
17299         "Bishnupriya",
17300         "বিষ্ণুপ্রিয়া মণিপুরী",
17301         "bpy"
17302     ],
17303     [
17304         "Breton",
17305         "brezhoneg",
17306         "br"
17307     ],
17308     [
17309         "Bosnian",
17310         "bosanski",
17311         "bs"
17312     ],
17313     [
17314         "Buginese",
17315         "ᨅᨔ ᨕᨘᨁᨗ",
17316         "bug"
17317     ],
17318     [
17319         "буряад",
17320         "буряад",
17321         "bxr"
17322     ],
17323     [
17324         "Catalan",
17325         "català",
17326         "ca"
17327     ],
17328     [
17329         "Chavacano de Zamboanga",
17330         "Chavacano de Zamboanga",
17331         "cbk-zam"
17332     ],
17333     [
17334         "Min Dong Chinese",
17335         "Mìng-dĕ̤ng-ngṳ̄",
17336         "cdo"
17337     ],
17338     [
17339         "Chechen",
17340         "нохчийн",
17341         "ce"
17342     ],
17343     [
17344         "Cebuano",
17345         "Cebuano",
17346         "ceb"
17347     ],
17348     [
17349         "Chamorro",
17350         "Chamoru",
17351         "ch"
17352     ],
17353     [
17354         "Cherokee",
17355         "ᏣᎳᎩ",
17356         "chr"
17357     ],
17358     [
17359         "Cheyenne",
17360         "Tsetsêhestâhese",
17361         "chy"
17362     ],
17363     [
17364         "Central Kurdish",
17365         "کوردیی ناوەندی",
17366         "ckb"
17367     ],
17368     [
17369         "Corsican",
17370         "corsu",
17371         "co"
17372     ],
17373     [
17374         "Cree",
17375         "Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ",
17376         "cr"
17377     ],
17378     [
17379         "Crimean Turkish",
17380         "qırımtatarca",
17381         "crh"
17382     ],
17383     [
17384         "Czech",
17385         "čeština",
17386         "cs"
17387     ],
17388     [
17389         "Kashubian",
17390         "kaszëbsczi",
17391         "csb"
17392     ],
17393     [
17394         "Church Slavic",
17395         "словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ",
17396         "cu"
17397     ],
17398     [
17399         "Chuvash",
17400         "Чӑвашла",
17401         "cv"
17402     ],
17403     [
17404         "Welsh",
17405         "Cymraeg",
17406         "cy"
17407     ],
17408     [
17409         "Danish",
17410         "dansk",
17411         "da"
17412     ],
17413     [
17414         "German",
17415         "Deutsch",
17416         "de"
17417     ],
17418     [
17419         "Zazaki",
17420         "Zazaki",
17421         "diq"
17422     ],
17423     [
17424         "Lower Sorbian",
17425         "dolnoserbski",
17426         "dsb"
17427     ],
17428     [
17429         "Divehi",
17430         "ދިވެހިބަސް",
17431         "dv"
17432     ],
17433     [
17434         "Dzongkha",
17435         "ཇོང་ཁ",
17436         "dz"
17437     ],
17438     [
17439         "Ewe",
17440         "eʋegbe",
17441         "ee"
17442     ],
17443     [
17444         "Greek",
17445         "Ελληνικά",
17446         "el"
17447     ],
17448     [
17449         "Emiliano-Romagnolo",
17450         "emiliàn e rumagnòl",
17451         "eml"
17452     ],
17453     [
17454         "English",
17455         "English",
17456         "en"
17457     ],
17458     [
17459         "Esperanto",
17460         "Esperanto",
17461         "eo"
17462     ],
17463     [
17464         "Spanish",
17465         "español",
17466         "es"
17467     ],
17468     [
17469         "Estonian",
17470         "eesti",
17471         "et"
17472     ],
17473     [
17474         "Basque",
17475         "euskara",
17476         "eu"
17477     ],
17478     [
17479         "Extremaduran",
17480         "estremeñu",
17481         "ext"
17482     ],
17483     [
17484         "Persian",
17485         "فارسی",
17486         "fa"
17487     ],
17488     [
17489         "Fulah",
17490         "Fulfulde",
17491         "ff"
17492     ],
17493     [
17494         "Finnish",
17495         "suomi",
17496         "fi"
17497     ],
17498     [
17499         "Võro",
17500         "Võro",
17501         "fiu-vro"
17502     ],
17503     [
17504         "Fijian",
17505         "Na Vosa Vakaviti",
17506         "fj"
17507     ],
17508     [
17509         "Faroese",
17510         "føroyskt",
17511         "fo"
17512     ],
17513     [
17514         "French",
17515         "français",
17516         "fr"
17517     ],
17518     [
17519         "Arpitan",
17520         "arpetan",
17521         "frp"
17522     ],
17523     [
17524         "Northern Frisian",
17525         "Nordfriisk",
17526         "frr"
17527     ],
17528     [
17529         "Friulian",
17530         "furlan",
17531         "fur"
17532     ],
17533     [
17534         "Western Frisian",
17535         "Frysk",
17536         "fy"
17537     ],
17538     [
17539         "Irish",
17540         "Gaeilge",
17541         "ga"
17542     ],
17543     [
17544         "Gagauz",
17545         "Gagauz",
17546         "gag"
17547     ],
17548     [
17549         "Gan Chinese",
17550         "贛語",
17551         "gan"
17552     ],
17553     [
17554         "Scottish Gaelic",
17555         "Gàidhlig",
17556         "gd"
17557     ],
17558     [
17559         "Galician",
17560         "galego",
17561         "gl"
17562     ],
17563     [
17564         "Gilaki",
17565         "گیلکی",
17566         "glk"
17567     ],
17568     [
17569         "Guarani",
17570         "Avañe'ẽ",
17571         "gn"
17572     ],
17573     [
17574         "Goan Konkani",
17575         "गोंयची कोंकणी / Gõychi Konknni",
17576         "gom"
17577     ],
17578     [
17579         "Gothic",
17580         "𐌲𐌿𐍄𐌹𐍃𐌺",
17581         "got"
17582     ],
17583     [
17584         "Gujarati",
17585         "ગુજરાતી",
17586         "gu"
17587     ],
17588     [
17589         "Manx",
17590         "Gaelg",
17591         "gv"
17592     ],
17593     [
17594         "Hausa",
17595         "Hausa",
17596         "ha"
17597     ],
17598     [
17599         "Hakka Chinese",
17600         "客家語/Hak-kâ-ngî",
17601         "hak"
17602     ],
17603     [
17604         "Hawaiian",
17605         "Hawaiʻi",
17606         "haw"
17607     ],
17608     [
17609         "Hebrew",
17610         "עברית",
17611         "he"
17612     ],
17613     [
17614         "Hindi",
17615         "हिन्दी",
17616         "hi"
17617     ],
17618     [
17619         "Fiji Hindi",
17620         "Fiji Hindi",
17621         "hif"
17622     ],
17623     [
17624         "Croatian",
17625         "hrvatski",
17626         "hr"
17627     ],
17628     [
17629         "Upper Sorbian",
17630         "hornjoserbsce",
17631         "hsb"
17632     ],
17633     [
17634         "Haitian Creole",
17635         "Kreyòl ayisyen",
17636         "ht"
17637     ],
17638     [
17639         "Hungarian",
17640         "magyar",
17641         "hu"
17642     ],
17643     [
17644         "Armenian",
17645         "Հայերեն",
17646         "hy"
17647     ],
17648     [
17649         "Interlingua",
17650         "interlingua",
17651         "ia"
17652     ],
17653     [
17654         "Indonesian",
17655         "Bahasa Indonesia",
17656         "id"
17657     ],
17658     [
17659         "Interlingue",
17660         "Interlingue",
17661         "ie"
17662     ],
17663     [
17664         "Igbo",
17665         "Igbo",
17666         "ig"
17667     ],
17668     [
17669         "Inupiaq",
17670         "Iñupiak",
17671         "ik"
17672     ],
17673     [
17674         "Iloko",
17675         "Ilokano",
17676         "ilo"
17677     ],
17678     [
17679         "Ido",
17680         "Ido",
17681         "io"
17682     ],
17683     [
17684         "Icelandic",
17685         "íslenska",
17686         "is"
17687     ],
17688     [
17689         "Italian",
17690         "italiano",
17691         "it"
17692     ],
17693     [
17694         "Inuktitut",
17695         "ᐃᓄᒃᑎᑐᑦ/inuktitut",
17696         "iu"
17697     ],
17698     [
17699         "Japanese",
17700         "日本語",
17701         "ja"
17702     ],
17703     [
17704         "Jamaican Creole English",
17705         "Patois",
17706         "jam"
17707     ],
17708     [
17709         "Lojban",
17710         "la .lojban.",
17711         "jbo"
17712     ],
17713     [
17714         "Javanese",
17715         "Basa Jawa",
17716         "jv"
17717     ],
17718     [
17719         "Georgian",
17720         "ქართული",
17721         "ka"
17722     ],
17723     [
17724         "Kara-Kalpak",
17725         "Qaraqalpaqsha",
17726         "kaa"
17727     ],
17728     [
17729         "Kabyle",
17730         "Taqbaylit",
17731         "kab"
17732     ],
17733     [
17734         "Kabardian",
17735         "Адыгэбзэ",
17736         "kbd"
17737     ],
17738     [
17739         "Kongo",
17740         "Kongo",
17741         "kg"
17742     ],
17743     [
17744         "Kikuyu",
17745         "Gĩkũyũ",
17746         "ki"
17747     ],
17748     [
17749         "Kazakh",
17750         "қазақша",
17751         "kk"
17752     ],
17753     [
17754         "Kalaallisut",
17755         "kalaallisut",
17756         "kl"
17757     ],
17758     [
17759         "Khmer",
17760         "ភាសាខ្មែរ",
17761         "km"
17762     ],
17763     [
17764         "Kannada",
17765         "ಕನ್ನಡ",
17766         "kn"
17767     ],
17768     [
17769         "Korean",
17770         "한국어",
17771         "ko"
17772     ],
17773     [
17774         "Komi-Permyak",
17775         "Перем Коми",
17776         "koi"
17777     ],
17778     [
17779         "Karachay-Balkar",
17780         "къарачай-малкъар",
17781         "krc"
17782     ],
17783     [
17784         "Kashmiri",
17785         "कॉशुर / کٲشُر",
17786         "ks"
17787     ],
17788     [
17789         "Colognian",
17790         "Ripoarisch",
17791         "ksh"
17792     ],
17793     [
17794         "Kurdish",
17795         "Kurdî",
17796         "ku"
17797     ],
17798     [
17799         "Komi",
17800         "коми",
17801         "kv"
17802     ],
17803     [
17804         "Cornish",
17805         "kernowek",
17806         "kw"
17807     ],
17808     [
17809         "Kyrgyz",
17810         "Кыргызча",
17811         "ky"
17812     ],
17813     [
17814         "Latin",
17815         "Latina",
17816         "la"
17817     ],
17818     [
17819         "Ladino",
17820         "Ladino",
17821         "lad"
17822     ],
17823     [
17824         "Luxembourgish",
17825         "Lëtzebuergesch",
17826         "lb"
17827     ],
17828     [
17829         "лакку",
17830         "лакку",
17831         "lbe"
17832     ],
17833     [
17834         "Lezghian",
17835         "лезги",
17836         "lez"
17837     ],
17838     [
17839         "Ganda",
17840         "Luganda",
17841         "lg"
17842     ],
17843     [
17844         "Limburgish",
17845         "Limburgs",
17846         "li"
17847     ],
17848     [
17849         "Ligurian",
17850         "Ligure",
17851         "lij"
17852     ],
17853     [
17854         "Lombard",
17855         "lumbaart",
17856         "lmo"
17857     ],
17858     [
17859         "Lingala",
17860         "lingála",
17861         "ln"
17862     ],
17863     [
17864         "Lao",
17865         "ລາວ",
17866         "lo"
17867     ],
17868     [
17869         "Northern Luri",
17870         "لۊری شومالی",
17871         "lrc"
17872     ],
17873     [
17874         "Lithuanian",
17875         "lietuvių",
17876         "lt"
17877     ],
17878     [
17879         "Latgalian",
17880         "latgaļu",
17881         "ltg"
17882     ],
17883     [
17884         "Latvian",
17885         "latviešu",
17886         "lv"
17887     ],
17888     [
17889         "Maithili",
17890         "मैथिली",
17891         "mai"
17892     ],
17893     [
17894         "Basa Banyumasan",
17895         "Basa Banyumasan",
17896         "map-bms"
17897     ],
17898     [
17899         "Moksha",
17900         "мокшень",
17901         "mdf"
17902     ],
17903     [
17904         "Malagasy",
17905         "Malagasy",
17906         "mg"
17907     ],
17908     [
17909         "Eastern Mari",
17910         "олык марий",
17911         "mhr"
17912     ],
17913     [
17914         "Maori",
17915         "Māori",
17916         "mi"
17917     ],
17918     [
17919         "Minangkabau",
17920         "Baso Minangkabau",
17921         "min"
17922     ],
17923     [
17924         "Macedonian",
17925         "македонски",
17926         "mk"
17927     ],
17928     [
17929         "Malayalam",
17930         "മലയാളം",
17931         "ml"
17932     ],
17933     [
17934         "Mongolian",
17935         "монгол",
17936         "mn"
17937     ],
17938     [
17939         "Marathi",
17940         "मराठी",
17941         "mr"
17942     ],
17943     [
17944         "Western Mari",
17945         "кырык мары",
17946         "mrj"
17947     ],
17948     [
17949         "Malay",
17950         "Bahasa Melayu",
17951         "ms"
17952     ],
17953     [
17954         "Maltese",
17955         "Malti",
17956         "mt"
17957     ],
17958     [
17959         "Mirandese",
17960         "Mirandés",
17961         "mwl"
17962     ],
17963     [
17964         "Burmese",
17965         "မြန်မာဘာသာ",
17966         "my"
17967     ],
17968     [
17969         "Erzya",
17970         "эрзянь",
17971         "myv"
17972     ],
17973     [
17974         "Mazanderani",
17975         "مازِرونی",
17976         "mzn"
17977     ],
17978     [
17979         "Nauru",
17980         "Dorerin Naoero",
17981         "na"
17982     ],
17983     [
17984         "Nāhuatl",
17985         "Nāhuatl",
17986         "nah"
17987     ],
17988     [
17989         "Neapolitan",
17990         "Napulitano",
17991         "nap"
17992     ],
17993     [
17994         "Low German",
17995         "Plattdüütsch",
17996         "nds"
17997     ],
17998     [
17999         "Low Saxon",
18000         "Nedersaksies",
18001         "nds-nl"
18002     ],
18003     [
18004         "Nepali",
18005         "नेपाली",
18006         "ne"
18007     ],
18008     [
18009         "Newari",
18010         "नेपाल भाषा",
18011         "new"
18012     ],
18013     [
18014         "Dutch",
18015         "Nederlands",
18016         "nl"
18017     ],
18018     [
18019         "Norwegian Nynorsk",
18020         "norsk nynorsk",
18021         "nn"
18022     ],
18023     [
18024         "Norwegian",
18025         "norsk bokmål",
18026         "no"
18027     ],
18028     [
18029         "Novial",
18030         "Novial",
18031         "nov"
18032     ],
18033     [
18034         "Nouormand",
18035         "Nouormand",
18036         "nrm"
18037     ],
18038     [
18039         "Northern Sotho",
18040         "Sesotho sa Leboa",
18041         "nso"
18042     ],
18043     [
18044         "Navajo",
18045         "Diné bizaad",
18046         "nv"
18047     ],
18048     [
18049         "Nyanja",
18050         "Chi-Chewa",
18051         "ny"
18052     ],
18053     [
18054         "Occitan",
18055         "occitan",
18056         "oc"
18057     ],
18058     [
18059         "Livvi-Karelian",
18060         "Livvinкarjala",
18061         "olo"
18062     ],
18063     [
18064         "Oromo",
18065         "Oromoo",
18066         "om"
18067     ],
18068     [
18069         "Oriya",
18070         "ଓଡ଼ିଆ",
18071         "or"
18072     ],
18073     [
18074         "Ossetic",
18075         "Ирон",
18076         "os"
18077     ],
18078     [
18079         "Punjabi",
18080         "ਪੰਜਾਬੀ",
18081         "pa"
18082     ],
18083     [
18084         "Pangasinan",
18085         "Pangasinan",
18086         "pag"
18087     ],
18088     [
18089         "Pampanga",
18090         "Kapampangan",
18091         "pam"
18092     ],
18093     [
18094         "Papiamento",
18095         "Papiamentu",
18096         "pap"
18097     ],
18098     [
18099         "Picard",
18100         "Picard",
18101         "pcd"
18102     ],
18103     [
18104         "Pennsylvania German",
18105         "Deitsch",
18106         "pdc"
18107     ],
18108     [
18109         "Palatine German",
18110         "Pälzisch",
18111         "pfl"
18112     ],
18113     [
18114         "Pali",
18115         "पालि",
18116         "pi"
18117     ],
18118     [
18119         "Norfuk / Pitkern",
18120         "Norfuk / Pitkern",
18121         "pih"
18122     ],
18123     [
18124         "Polish",
18125         "polski",
18126         "pl"
18127     ],
18128     [
18129         "Piedmontese",
18130         "Piemontèis",
18131         "pms"
18132     ],
18133     [
18134         "Western Punjabi",
18135         "پنجابی",
18136         "pnb"
18137     ],
18138     [
18139         "Pontic",
18140         "Ποντιακά",
18141         "pnt"
18142     ],
18143     [
18144         "Pashto",
18145         "پښتو",
18146         "ps"
18147     ],
18148     [
18149         "Portuguese",
18150         "português",
18151         "pt"
18152     ],
18153     [
18154         "Quechua",
18155         "Runa Simi",
18156         "qu"
18157     ],
18158     [
18159         "Romansh",
18160         "rumantsch",
18161         "rm"
18162     ],
18163     [
18164         "Romani",
18165         "Romani",
18166         "rmy"
18167     ],
18168     [
18169         "Rundi",
18170         "Kirundi",
18171         "rn"
18172     ],
18173     [
18174         "Romanian",
18175         "română",
18176         "ro"
18177     ],
18178     [
18179         "Aromanian",
18180         "armãneashti",
18181         "roa-rup"
18182     ],
18183     [
18184         "tarandíne",
18185         "tarandíne",
18186         "roa-tara"
18187     ],
18188     [
18189         "Russian",
18190         "русский",
18191         "ru"
18192     ],
18193     [
18194         "Rusyn",
18195         "русиньскый",
18196         "rue"
18197     ],
18198     [
18199         "Kinyarwanda",
18200         "Kinyarwanda",
18201         "rw"
18202     ],
18203     [
18204         "Sanskrit",
18205         "संस्कृतम्",
18206         "sa"
18207     ],
18208     [
18209         "Sakha",
18210         "саха тыла",
18211         "sah"
18212     ],
18213     [
18214         "Sardinian",
18215         "sardu",
18216         "sc"
18217     ],
18218     [
18219         "Sicilian",
18220         "sicilianu",
18221         "scn"
18222     ],
18223     [
18224         "Scots",
18225         "Scots",
18226         "sco"
18227     ],
18228     [
18229         "Sindhi",
18230         "سنڌي",
18231         "sd"
18232     ],
18233     [
18234         "Northern Sami",
18235         "sámegiella",
18236         "se"
18237     ],
18238     [
18239         "Sango",
18240         "Sängö",
18241         "sg"
18242     ],
18243     [
18244         "Serbo-Croatian",
18245         "srpskohrvatski / српскохрватски",
18246         "sh"
18247     ],
18248     [
18249         "Sinhala",
18250         "සිංහල",
18251         "si"
18252     ],
18253     [
18254         "Simple English",
18255         "Simple English",
18256         "simple"
18257     ],
18258     [
18259         "Slovak",
18260         "slovenčina",
18261         "sk"
18262     ],
18263     [
18264         "Slovenian",
18265         "slovenščina",
18266         "sl"
18267     ],
18268     [
18269         "Samoan",
18270         "Gagana Samoa",
18271         "sm"
18272     ],
18273     [
18274         "Shona",
18275         "chiShona",
18276         "sn"
18277     ],
18278     [
18279         "Somali",
18280         "Soomaaliga",
18281         "so"
18282     ],
18283     [
18284         "Albanian",
18285         "shqip",
18286         "sq"
18287     ],
18288     [
18289         "Serbian",
18290         "српски / srpski",
18291         "sr"
18292     ],
18293     [
18294         "Sranan Tongo",
18295         "Sranantongo",
18296         "srn"
18297     ],
18298     [
18299         "Swati",
18300         "SiSwati",
18301         "ss"
18302     ],
18303     [
18304         "Southern Sotho",
18305         "Sesotho",
18306         "st"
18307     ],
18308     [
18309         "Saterland Frisian",
18310         "Seeltersk",
18311         "stq"
18312     ],
18313     [
18314         "Sundanese",
18315         "Basa Sunda",
18316         "su"
18317     ],
18318     [
18319         "Swedish",
18320         "svenska",
18321         "sv"
18322     ],
18323     [
18324         "Swahili",
18325         "Kiswahili",
18326         "sw"
18327     ],
18328     [
18329         "Silesian",
18330         "ślůnski",
18331         "szl"
18332     ],
18333     [
18334         "Tamil",
18335         "தமிழ்",
18336         "ta"
18337     ],
18338     [
18339         "Tulu",
18340         "ತುಳು",
18341         "tcy"
18342     ],
18343     [
18344         "Telugu",
18345         "తెలుగు",
18346         "te"
18347     ],
18348     [
18349         "Tetum",
18350         "tetun",
18351         "tet"
18352     ],
18353     [
18354         "Tajik",
18355         "тоҷикӣ",
18356         "tg"
18357     ],
18358     [
18359         "Thai",
18360         "ไทย",
18361         "th"
18362     ],
18363     [
18364         "Tigrinya",
18365         "ትግርኛ",
18366         "ti"
18367     ],
18368     [
18369         "Turkmen",
18370         "Türkmençe",
18371         "tk"
18372     ],
18373     [
18374         "Tagalog",
18375         "Tagalog",
18376         "tl"
18377     ],
18378     [
18379         "Tswana",
18380         "Setswana",
18381         "tn"
18382     ],
18383     [
18384         "Tongan",
18385         "lea faka-Tonga",
18386         "to"
18387     ],
18388     [
18389         "Tok Pisin",
18390         "Tok Pisin",
18391         "tpi"
18392     ],
18393     [
18394         "Turkish",
18395         "Türkçe",
18396         "tr"
18397     ],
18398     [
18399         "Tsonga",
18400         "Xitsonga",
18401         "ts"
18402     ],
18403     [
18404         "Tatar",
18405         "татарча/tatarça",
18406         "tt"
18407     ],
18408     [
18409         "Tumbuka",
18410         "chiTumbuka",
18411         "tum"
18412     ],
18413     [
18414         "Twi",
18415         "Twi",
18416         "tw"
18417     ],
18418     [
18419         "Tahitian",
18420         "reo tahiti",
18421         "ty"
18422     ],
18423     [
18424         "Tuvinian",
18425         "тыва дыл",
18426         "tyv"
18427     ],
18428     [
18429         "Udmurt",
18430         "удмурт",
18431         "udm"
18432     ],
18433     [
18434         "Uyghur",
18435         "ئۇيغۇرچە / Uyghurche",
18436         "ug"
18437     ],
18438     [
18439         "Ukrainian",
18440         "українська",
18441         "uk"
18442     ],
18443     [
18444         "Urdu",
18445         "اردو",
18446         "ur"
18447     ],
18448     [
18449         "Uzbek",
18450         "oʻzbekcha/ўзбекча",
18451         "uz"
18452     ],
18453     [
18454         "Venda",
18455         "Tshivenda",
18456         "ve"
18457     ],
18458     [
18459         "Venetian",
18460         "vèneto",
18461         "vec"
18462     ],
18463     [
18464         "Veps",
18465         "vepsän kel’",
18466         "vep"
18467     ],
18468     [
18469         "Vietnamese",
18470         "Tiếng Việt",
18471         "vi"
18472     ],
18473     [
18474         "West Flemish",
18475         "West-Vlams",
18476         "vls"
18477     ],
18478     [
18479         "Volapük",
18480         "Volapük",
18481         "vo"
18482     ],
18483     [
18484         "Walloon",
18485         "walon",
18486         "wa"
18487     ],
18488     [
18489         "Waray",
18490         "Winaray",
18491         "war"
18492     ],
18493     [
18494         "Wolof",
18495         "Wolof",
18496         "wo"
18497     ],
18498     [
18499         "Wu Chinese",
18500         "吴语",
18501         "wuu"
18502     ],
18503     [
18504         "Kalmyk",
18505         "хальмг",
18506         "xal"
18507     ],
18508     [
18509         "Xhosa",
18510         "isiXhosa",
18511         "xh"
18512     ],
18513     [
18514         "Mingrelian",
18515         "მარგალური",
18516         "xmf"
18517     ],
18518     [
18519         "Yiddish",
18520         "ייִדיש",
18521         "yi"
18522     ],
18523     [
18524         "Yoruba",
18525         "Yorùbá",
18526         "yo"
18527     ],
18528     [
18529         "Zhuang",
18530         "Vahcuengh",
18531         "za"
18532     ],
18533     [
18534         "Zeelandic",
18535         "Zeêuws",
18536         "zea"
18537     ],
18538     [
18539         "Chinese",
18540         "中文",
18541         "zh"
18542     ],
18543     [
18544         "Classical Chinese",
18545         "文言",
18546         "zh-classical"
18547     ],
18548     [
18549         "Chinese (Min Nan)",
18550         "Bân-lâm-gú",
18551         "zh-min-nan"
18552     ],
18553     [
18554         "Cantonese",
18555         "粵語",
18556         "zh-yue"
18557     ],
18558     [
18559         "Zulu",
18560         "isiZulu",
18561         "zu"
18562     ]
18563 ];
18564
18565 var dataFeatureIcons =  {
18566         "circle-stroked-24": {"x":0,"y":0,"width":24,"height":24},
18567         "circle-stroked-18": {"x":24,"y":0,"width":18,"height":18},
18568         "circle-stroked-12": {"x":42,"y":0,"width":12,"height":12},
18569         "circle-24": {"x":54,"y":0,"width":24,"height":24},
18570         "circle-18": {"x":78,"y":0,"width":18,"height":18},
18571         "circle-12": {"x":96,"y":0,"width":12,"height":12},
18572         "square-stroked-24": {"x":108,"y":0,"width":24,"height":24},
18573         "square-stroked-18": {"x":132,"y":0,"width":18,"height":18},
18574         "square-stroked-12": {"x":150,"y":0,"width":12,"height":12},
18575         "square-24": {"x":162,"y":0,"width":24,"height":24},
18576         "square-18": {"x":186,"y":0,"width":18,"height":18},
18577         "square-12": {"x":204,"y":0,"width":12,"height":12},
18578         "triangle-stroked-24": {"x":216,"y":0,"width":24,"height":24},
18579         "triangle-stroked-18": {"x":240,"y":0,"width":18,"height":18},
18580         "triangle-stroked-12": {"x":258,"y":0,"width":12,"height":12},
18581         "triangle-24": {"x":0,"y":24,"width":24,"height":24},
18582         "triangle-18": {"x":24,"y":24,"width":18,"height":18},
18583         "triangle-12": {"x":42,"y":24,"width":12,"height":12},
18584         "star-stroked-24": {"x":54,"y":24,"width":24,"height":24},
18585         "star-stroked-18": {"x":78,"y":24,"width":18,"height":18},
18586         "star-stroked-12": {"x":96,"y":24,"width":12,"height":12},
18587         "star-24": {"x":108,"y":24,"width":24,"height":24},
18588         "star-18": {"x":132,"y":24,"width":18,"height":18},
18589         "star-12": {"x":150,"y":24,"width":12,"height":12},
18590         "cross-24": {"x":162,"y":24,"width":24,"height":24},
18591         "cross-18": {"x":186,"y":24,"width":18,"height":18},
18592         "cross-12": {"x":204,"y":24,"width":12,"height":12},
18593         "marker-stroked-24": {"x":216,"y":24,"width":24,"height":24},
18594         "marker-stroked-18": {"x":240,"y":24,"width":18,"height":18},
18595         "marker-stroked-12": {"x":258,"y":24,"width":12,"height":12},
18596         "marker-24": {"x":0,"y":48,"width":24,"height":24},
18597         "marker-18": {"x":24,"y":48,"width":18,"height":18},
18598         "marker-12": {"x":42,"y":48,"width":12,"height":12},
18599         "religious-jewish-24": {"x":54,"y":48,"width":24,"height":24},
18600         "religious-jewish-18": {"x":78,"y":48,"width":18,"height":18},
18601         "religious-jewish-12": {"x":96,"y":48,"width":12,"height":12},
18602         "religious-christian-24": {"x":108,"y":48,"width":24,"height":24},
18603         "religious-christian-18": {"x":132,"y":48,"width":18,"height":18},
18604         "religious-christian-12": {"x":150,"y":48,"width":12,"height":12},
18605         "religious-muslim-24": {"x":162,"y":48,"width":24,"height":24},
18606         "religious-muslim-18": {"x":186,"y":48,"width":18,"height":18},
18607         "religious-muslim-12": {"x":204,"y":48,"width":12,"height":12},
18608         "cemetery-24": {"x":216,"y":48,"width":24,"height":24},
18609         "cemetery-18": {"x":240,"y":48,"width":18,"height":18},
18610         "cemetery-12": {"x":258,"y":48,"width":12,"height":12},
18611         "rocket-24": {"x":0,"y":72,"width":24,"height":24},
18612         "rocket-18": {"x":24,"y":72,"width":18,"height":18},
18613         "rocket-12": {"x":42,"y":72,"width":12,"height":12},
18614         "airport-24": {"x":54,"y":72,"width":24,"height":24},
18615         "airport-18": {"x":78,"y":72,"width":18,"height":18},
18616         "airport-12": {"x":96,"y":72,"width":12,"height":12},
18617         "heliport-24": {"x":108,"y":72,"width":24,"height":24},
18618         "heliport-18": {"x":132,"y":72,"width":18,"height":18},
18619         "heliport-12": {"x":150,"y":72,"width":12,"height":12},
18620         "rail-24": {"x":162,"y":72,"width":24,"height":24},
18621         "rail-18": {"x":186,"y":72,"width":18,"height":18},
18622         "rail-12": {"x":204,"y":72,"width":12,"height":12},
18623         "rail-metro-24": {"x":216,"y":72,"width":24,"height":24},
18624         "rail-metro-18": {"x":240,"y":72,"width":18,"height":18},
18625         "rail-metro-12": {"x":258,"y":72,"width":12,"height":12},
18626         "rail-light-24": {"x":0,"y":96,"width":24,"height":24},
18627         "rail-light-18": {"x":24,"y":96,"width":18,"height":18},
18628         "rail-light-12": {"x":42,"y":96,"width":12,"height":12},
18629         "bus-24": {"x":54,"y":96,"width":24,"height":24},
18630         "bus-18": {"x":78,"y":96,"width":18,"height":18},
18631         "bus-12": {"x":96,"y":96,"width":12,"height":12},
18632         "fuel-24": {"x":108,"y":96,"width":24,"height":24},
18633         "fuel-18": {"x":132,"y":96,"width":18,"height":18},
18634         "fuel-12": {"x":150,"y":96,"width":12,"height":12},
18635         "parking-24": {"x":162,"y":96,"width":24,"height":24},
18636         "parking-18": {"x":186,"y":96,"width":18,"height":18},
18637         "parking-12": {"x":204,"y":96,"width":12,"height":12},
18638         "parking-garage-24": {"x":216,"y":96,"width":24,"height":24},
18639         "parking-garage-18": {"x":240,"y":96,"width":18,"height":18},
18640         "parking-garage-12": {"x":258,"y":96,"width":12,"height":12},
18641         "airfield-24": {"x":0,"y":120,"width":24,"height":24},
18642         "airfield-18": {"x":24,"y":120,"width":18,"height":18},
18643         "airfield-12": {"x":42,"y":120,"width":12,"height":12},
18644         "roadblock-24": {"x":54,"y":120,"width":24,"height":24},
18645         "roadblock-18": {"x":78,"y":120,"width":18,"height":18},
18646         "roadblock-12": {"x":96,"y":120,"width":12,"height":12},
18647         "ferry-24": {"x":108,"y":120,"width":24,"height":24},
18648         "ferry-18": {"x":132,"y":120,"width":18,"height":18},
18649         "ferry-12": {"x":150,"y":120,"width":12,"height":12},
18650         "harbor-24": {"x":162,"y":120,"width":24,"height":24},
18651         "harbor-18": {"x":186,"y":120,"width":18,"height":18},
18652         "harbor-12": {"x":204,"y":120,"width":12,"height":12},
18653         "bicycle-24": {"x":216,"y":120,"width":24,"height":24},
18654         "bicycle-18": {"x":240,"y":120,"width":18,"height":18},
18655         "bicycle-12": {"x":258,"y":120,"width":12,"height":12},
18656         "park-24": {"x":0,"y":144,"width":24,"height":24},
18657         "park-18": {"x":24,"y":144,"width":18,"height":18},
18658         "park-12": {"x":42,"y":144,"width":12,"height":12},
18659         "park2-24": {"x":54,"y":144,"width":24,"height":24},
18660         "park2-18": {"x":78,"y":144,"width":18,"height":18},
18661         "park2-12": {"x":96,"y":144,"width":12,"height":12},
18662         "museum-24": {"x":108,"y":144,"width":24,"height":24},
18663         "museum-18": {"x":132,"y":144,"width":18,"height":18},
18664         "museum-12": {"x":150,"y":144,"width":12,"height":12},
18665         "lodging-24": {"x":162,"y":144,"width":24,"height":24},
18666         "lodging-18": {"x":186,"y":144,"width":18,"height":18},
18667         "lodging-12": {"x":204,"y":144,"width":12,"height":12},
18668         "monument-24": {"x":216,"y":144,"width":24,"height":24},
18669         "monument-18": {"x":240,"y":144,"width":18,"height":18},
18670         "monument-12": {"x":258,"y":144,"width":12,"height":12},
18671         "zoo-24": {"x":0,"y":168,"width":24,"height":24},
18672         "zoo-18": {"x":24,"y":168,"width":18,"height":18},
18673         "zoo-12": {"x":42,"y":168,"width":12,"height":12},
18674         "garden-24": {"x":54,"y":168,"width":24,"height":24},
18675         "garden-18": {"x":78,"y":168,"width":18,"height":18},
18676         "garden-12": {"x":96,"y":168,"width":12,"height":12},
18677         "campsite-24": {"x":108,"y":168,"width":24,"height":24},
18678         "campsite-18": {"x":132,"y":168,"width":18,"height":18},
18679         "campsite-12": {"x":150,"y":168,"width":12,"height":12},
18680         "theatre-24": {"x":162,"y":168,"width":24,"height":24},
18681         "theatre-18": {"x":186,"y":168,"width":18,"height":18},
18682         "theatre-12": {"x":204,"y":168,"width":12,"height":12},
18683         "art-gallery-24": {"x":216,"y":168,"width":24,"height":24},
18684         "art-gallery-18": {"x":240,"y":168,"width":18,"height":18},
18685         "art-gallery-12": {"x":258,"y":168,"width":12,"height":12},
18686         "pitch-24": {"x":0,"y":192,"width":24,"height":24},
18687         "pitch-18": {"x":24,"y":192,"width":18,"height":18},
18688         "pitch-12": {"x":42,"y":192,"width":12,"height":12},
18689         "soccer-24": {"x":54,"y":192,"width":24,"height":24},
18690         "soccer-18": {"x":78,"y":192,"width":18,"height":18},
18691         "soccer-12": {"x":96,"y":192,"width":12,"height":12},
18692         "america-football-24": {"x":108,"y":192,"width":24,"height":24},
18693         "america-football-18": {"x":132,"y":192,"width":18,"height":18},
18694         "america-football-12": {"x":150,"y":192,"width":12,"height":12},
18695         "tennis-24": {"x":162,"y":192,"width":24,"height":24},
18696         "tennis-18": {"x":186,"y":192,"width":18,"height":18},
18697         "tennis-12": {"x":204,"y":192,"width":12,"height":12},
18698         "basketball-24": {"x":216,"y":192,"width":24,"height":24},
18699         "basketball-18": {"x":240,"y":192,"width":18,"height":18},
18700         "basketball-12": {"x":258,"y":192,"width":12,"height":12},
18701         "baseball-24": {"x":0,"y":216,"width":24,"height":24},
18702         "baseball-18": {"x":24,"y":216,"width":18,"height":18},
18703         "baseball-12": {"x":42,"y":216,"width":12,"height":12},
18704         "golf-24": {"x":54,"y":216,"width":24,"height":24},
18705         "golf-18": {"x":78,"y":216,"width":18,"height":18},
18706         "golf-12": {"x":96,"y":216,"width":12,"height":12},
18707         "swimming-24": {"x":108,"y":216,"width":24,"height":24},
18708         "swimming-18": {"x":132,"y":216,"width":18,"height":18},
18709         "swimming-12": {"x":150,"y":216,"width":12,"height":12},
18710         "cricket-24": {"x":162,"y":216,"width":24,"height":24},
18711         "cricket-18": {"x":186,"y":216,"width":18,"height":18},
18712         "cricket-12": {"x":204,"y":216,"width":12,"height":12},
18713         "skiing-24": {"x":216,"y":216,"width":24,"height":24},
18714         "skiing-18": {"x":240,"y":216,"width":18,"height":18},
18715         "skiing-12": {"x":258,"y":216,"width":12,"height":12},
18716         "school-24": {"x":0,"y":240,"width":24,"height":24},
18717         "school-18": {"x":24,"y":240,"width":18,"height":18},
18718         "school-12": {"x":42,"y":240,"width":12,"height":12},
18719         "college-24": {"x":54,"y":240,"width":24,"height":24},
18720         "college-18": {"x":78,"y":240,"width":18,"height":18},
18721         "college-12": {"x":96,"y":240,"width":12,"height":12},
18722         "library-24": {"x":108,"y":240,"width":24,"height":24},
18723         "library-18": {"x":132,"y":240,"width":18,"height":18},
18724         "library-12": {"x":150,"y":240,"width":12,"height":12},
18725         "post-24": {"x":162,"y":240,"width":24,"height":24},
18726         "post-18": {"x":186,"y":240,"width":18,"height":18},
18727         "post-12": {"x":204,"y":240,"width":12,"height":12},
18728         "fire-station-24": {"x":216,"y":240,"width":24,"height":24},
18729         "fire-station-18": {"x":240,"y":240,"width":18,"height":18},
18730         "fire-station-12": {"x":258,"y":240,"width":12,"height":12},
18731         "town-hall-24": {"x":0,"y":264,"width":24,"height":24},
18732         "town-hall-18": {"x":24,"y":264,"width":18,"height":18},
18733         "town-hall-12": {"x":42,"y":264,"width":12,"height":12},
18734         "police-24": {"x":54,"y":264,"width":24,"height":24},
18735         "police-18": {"x":78,"y":264,"width":18,"height":18},
18736         "police-12": {"x":96,"y":264,"width":12,"height":12},
18737         "prison-24": {"x":108,"y":264,"width":24,"height":24},
18738         "prison-18": {"x":132,"y":264,"width":18,"height":18},
18739         "prison-12": {"x":150,"y":264,"width":12,"height":12},
18740         "embassy-24": {"x":162,"y":264,"width":24,"height":24},
18741         "embassy-18": {"x":186,"y":264,"width":18,"height":18},
18742         "embassy-12": {"x":204,"y":264,"width":12,"height":12},
18743         "beer-24": {"x":216,"y":264,"width":24,"height":24},
18744         "beer-18": {"x":240,"y":264,"width":18,"height":18},
18745         "beer-12": {"x":258,"y":264,"width":12,"height":12},
18746         "restaurant-24": {"x":0,"y":288,"width":24,"height":24},
18747         "restaurant-18": {"x":24,"y":288,"width":18,"height":18},
18748         "restaurant-12": {"x":42,"y":288,"width":12,"height":12},
18749         "cafe-24": {"x":54,"y":288,"width":24,"height":24},
18750         "cafe-18": {"x":78,"y":288,"width":18,"height":18},
18751         "cafe-12": {"x":96,"y":288,"width":12,"height":12},
18752         "shop-24": {"x":108,"y":288,"width":24,"height":24},
18753         "shop-18": {"x":132,"y":288,"width":18,"height":18},
18754         "shop-12": {"x":150,"y":288,"width":12,"height":12},
18755         "fast-food-24": {"x":162,"y":288,"width":24,"height":24},
18756         "fast-food-18": {"x":186,"y":288,"width":18,"height":18},
18757         "fast-food-12": {"x":204,"y":288,"width":12,"height":12},
18758         "bar-24": {"x":216,"y":288,"width":24,"height":24},
18759         "bar-18": {"x":240,"y":288,"width":18,"height":18},
18760         "bar-12": {"x":258,"y":288,"width":12,"height":12},
18761         "bank-24": {"x":0,"y":312,"width":24,"height":24},
18762         "bank-18": {"x":24,"y":312,"width":18,"height":18},
18763         "bank-12": {"x":42,"y":312,"width":12,"height":12},
18764         "grocery-24": {"x":54,"y":312,"width":24,"height":24},
18765         "grocery-18": {"x":78,"y":312,"width":18,"height":18},
18766         "grocery-12": {"x":96,"y":312,"width":12,"height":12},
18767         "cinema-24": {"x":108,"y":312,"width":24,"height":24},
18768         "cinema-18": {"x":132,"y":312,"width":18,"height":18},
18769         "cinema-12": {"x":150,"y":312,"width":12,"height":12},
18770         "pharmacy-24": {"x":162,"y":312,"width":24,"height":24},
18771         "pharmacy-18": {"x":186,"y":312,"width":18,"height":18},
18772         "pharmacy-12": {"x":204,"y":312,"width":12,"height":12},
18773         "hospital-24": {"x":216,"y":312,"width":24,"height":24},
18774         "hospital-18": {"x":240,"y":312,"width":18,"height":18},
18775         "hospital-12": {"x":258,"y":312,"width":12,"height":12},
18776         "danger-24": {"x":0,"y":336,"width":24,"height":24},
18777         "danger-18": {"x":24,"y":336,"width":18,"height":18},
18778         "danger-12": {"x":42,"y":336,"width":12,"height":12},
18779         "industrial-24": {"x":54,"y":336,"width":24,"height":24},
18780         "industrial-18": {"x":78,"y":336,"width":18,"height":18},
18781         "industrial-12": {"x":96,"y":336,"width":12,"height":12},
18782         "warehouse-24": {"x":108,"y":336,"width":24,"height":24},
18783         "warehouse-18": {"x":132,"y":336,"width":18,"height":18},
18784         "warehouse-12": {"x":150,"y":336,"width":12,"height":12},
18785         "commercial-24": {"x":162,"y":336,"width":24,"height":24},
18786         "commercial-18": {"x":186,"y":336,"width":18,"height":18},
18787         "commercial-12": {"x":204,"y":336,"width":12,"height":12},
18788         "building-24": {"x":216,"y":336,"width":24,"height":24},
18789         "building-18": {"x":240,"y":336,"width":18,"height":18},
18790         "building-12": {"x":258,"y":336,"width":12,"height":12},
18791         "place-of-worship-24": {"x":0,"y":360,"width":24,"height":24},
18792         "place-of-worship-18": {"x":24,"y":360,"width":18,"height":18},
18793         "place-of-worship-12": {"x":42,"y":360,"width":12,"height":12},
18794         "alcohol-shop-24": {"x":54,"y":360,"width":24,"height":24},
18795         "alcohol-shop-18": {"x":78,"y":360,"width":18,"height":18},
18796         "alcohol-shop-12": {"x":96,"y":360,"width":12,"height":12},
18797         "logging-24": {"x":108,"y":360,"width":24,"height":24},
18798         "logging-18": {"x":132,"y":360,"width":18,"height":18},
18799         "logging-12": {"x":150,"y":360,"width":12,"height":12},
18800         "oil-well-24": {"x":162,"y":360,"width":24,"height":24},
18801         "oil-well-18": {"x":186,"y":360,"width":18,"height":18},
18802         "oil-well-12": {"x":204,"y":360,"width":12,"height":12},
18803         "slaughterhouse-24": {"x":216,"y":360,"width":24,"height":24},
18804         "slaughterhouse-18": {"x":240,"y":360,"width":18,"height":18},
18805         "slaughterhouse-12": {"x":258,"y":360,"width":12,"height":12},
18806         "dam-24": {"x":0,"y":384,"width":24,"height":24},
18807         "dam-18": {"x":24,"y":384,"width":18,"height":18},
18808         "dam-12": {"x":42,"y":384,"width":12,"height":12},
18809         "water-24": {"x":54,"y":384,"width":24,"height":24},
18810         "water-18": {"x":78,"y":384,"width":18,"height":18},
18811         "water-12": {"x":96,"y":384,"width":12,"height":12},
18812         "wetland-24": {"x":108,"y":384,"width":24,"height":24},
18813         "wetland-18": {"x":132,"y":384,"width":18,"height":18},
18814         "wetland-12": {"x":150,"y":384,"width":12,"height":12},
18815         "disability-24": {"x":162,"y":384,"width":24,"height":24},
18816         "disability-18": {"x":186,"y":384,"width":18,"height":18},
18817         "disability-12": {"x":204,"y":384,"width":12,"height":12},
18818         "telephone-24": {"x":216,"y":384,"width":24,"height":24},
18819         "telephone-18": {"x":240,"y":384,"width":18,"height":18},
18820         "telephone-12": {"x":258,"y":384,"width":12,"height":12},
18821         "emergency-telephone-24": {"x":0,"y":408,"width":24,"height":24},
18822         "emergency-telephone-18": {"x":24,"y":408,"width":18,"height":18},
18823         "emergency-telephone-12": {"x":42,"y":408,"width":12,"height":12},
18824         "toilets-24": {"x":54,"y":408,"width":24,"height":24},
18825         "toilets-18": {"x":78,"y":408,"width":18,"height":18},
18826         "toilets-12": {"x":96,"y":408,"width":12,"height":12},
18827         "waste-basket-24": {"x":108,"y":408,"width":24,"height":24},
18828         "waste-basket-18": {"x":132,"y":408,"width":18,"height":18},
18829         "waste-basket-12": {"x":150,"y":408,"width":12,"height":12},
18830         "music-24": {"x":162,"y":408,"width":24,"height":24},
18831         "music-18": {"x":186,"y":408,"width":18,"height":18},
18832         "music-12": {"x":204,"y":408,"width":12,"height":12},
18833         "land-use-24": {"x":216,"y":408,"width":24,"height":24},
18834         "land-use-18": {"x":240,"y":408,"width":18,"height":18},
18835         "land-use-12": {"x":258,"y":408,"width":12,"height":12},
18836         "city-24": {"x":0,"y":432,"width":24,"height":24},
18837         "city-18": {"x":24,"y":432,"width":18,"height":18},
18838         "city-12": {"x":42,"y":432,"width":12,"height":12},
18839         "town-24": {"x":54,"y":432,"width":24,"height":24},
18840         "town-18": {"x":78,"y":432,"width":18,"height":18},
18841         "town-12": {"x":96,"y":432,"width":12,"height":12},
18842         "village-24": {"x":108,"y":432,"width":24,"height":24},
18843         "village-18": {"x":132,"y":432,"width":18,"height":18},
18844         "village-12": {"x":150,"y":432,"width":12,"height":12},
18845         "farm-24": {"x":162,"y":432,"width":24,"height":24},
18846         "farm-18": {"x":186,"y":432,"width":18,"height":18},
18847         "farm-12": {"x":204,"y":432,"width":12,"height":12},
18848         "bakery-24": {"x":216,"y":432,"width":24,"height":24},
18849         "bakery-18": {"x":240,"y":432,"width":18,"height":18},
18850         "bakery-12": {"x":258,"y":432,"width":12,"height":12},
18851         "dog-park-24": {"x":0,"y":456,"width":24,"height":24},
18852         "dog-park-18": {"x":24,"y":456,"width":18,"height":18},
18853         "dog-park-12": {"x":42,"y":456,"width":12,"height":12},
18854         "lighthouse-24": {"x":54,"y":456,"width":24,"height":24},
18855         "lighthouse-18": {"x":78,"y":456,"width":18,"height":18},
18856         "lighthouse-12": {"x":96,"y":456,"width":12,"height":12},
18857         "clothing-store-24": {"x":108,"y":456,"width":24,"height":24},
18858         "clothing-store-18": {"x":132,"y":456,"width":18,"height":18},
18859         "clothing-store-12": {"x":150,"y":456,"width":12,"height":12},
18860         "polling-place-24": {"x":162,"y":456,"width":24,"height":24},
18861         "polling-place-18": {"x":186,"y":456,"width":18,"height":18},
18862         "polling-place-12": {"x":204,"y":456,"width":12,"height":12},
18863         "playground-24": {"x":216,"y":456,"width":24,"height":24},
18864         "playground-18": {"x":240,"y":456,"width":18,"height":18},
18865         "playground-12": {"x":258,"y":456,"width":12,"height":12},
18866         "entrance-24": {"x":0,"y":480,"width":24,"height":24},
18867         "entrance-18": {"x":24,"y":480,"width":18,"height":18},
18868         "entrance-12": {"x":42,"y":480,"width":12,"height":12},
18869         "heart-24": {"x":54,"y":480,"width":24,"height":24},
18870         "heart-18": {"x":78,"y":480,"width":18,"height":18},
18871         "heart-12": {"x":96,"y":480,"width":12,"height":12},
18872         "london-underground-24": {"x":108,"y":480,"width":24,"height":24},
18873         "london-underground-18": {"x":132,"y":480,"width":18,"height":18},
18874         "london-underground-12": {"x":150,"y":480,"width":12,"height":12},
18875         "minefield-24": {"x":162,"y":480,"width":24,"height":24},
18876         "minefield-18": {"x":186,"y":480,"width":18,"height":18},
18877         "minefield-12": {"x":204,"y":480,"width":12,"height":12},
18878         "rail-underground-24": {"x":216,"y":480,"width":24,"height":24},
18879         "rail-underground-18": {"x":240,"y":480,"width":18,"height":18},
18880         "rail-underground-12": {"x":258,"y":480,"width":12,"height":12},
18881         "rail-above-24": {"x":0,"y":504,"width":24,"height":24},
18882         "rail-above-18": {"x":24,"y":504,"width":18,"height":18},
18883         "rail-above-12": {"x":42,"y":504,"width":12,"height":12},
18884         "camera-24": {"x":54,"y":504,"width":24,"height":24},
18885         "camera-18": {"x":78,"y":504,"width":18,"height":18},
18886         "camera-12": {"x":96,"y":504,"width":12,"height":12},
18887         "laundry-24": {"x":108,"y":504,"width":24,"height":24},
18888         "laundry-18": {"x":132,"y":504,"width":18,"height":18},
18889         "laundry-12": {"x":150,"y":504,"width":12,"height":12},
18890         "car-24": {"x":162,"y":504,"width":24,"height":24},
18891         "car-18": {"x":186,"y":504,"width":18,"height":18},
18892         "car-12": {"x":204,"y":504,"width":12,"height":12},
18893         "suitcase-24": {"x":216,"y":504,"width":24,"height":24},
18894         "suitcase-18": {"x":240,"y":504,"width":18,"height":18},
18895         "suitcase-12": {"x":258,"y":504,"width":12,"height":12},
18896         "hairdresser-24": {"x":0,"y":528,"width":24,"height":24},
18897         "hairdresser-18": {"x":24,"y":528,"width":18,"height":18},
18898         "hairdresser-12": {"x":42,"y":528,"width":12,"height":12},
18899         "chemist-24": {"x":54,"y":528,"width":24,"height":24},
18900         "chemist-18": {"x":78,"y":528,"width":18,"height":18},
18901         "chemist-12": {"x":96,"y":528,"width":12,"height":12},
18902         "mobilephone-24": {"x":108,"y":528,"width":24,"height":24},
18903         "mobilephone-18": {"x":132,"y":528,"width":18,"height":18},
18904         "mobilephone-12": {"x":150,"y":528,"width":12,"height":12},
18905         "scooter-24": {"x":162,"y":528,"width":24,"height":24},
18906         "scooter-18": {"x":186,"y":528,"width":18,"height":18},
18907         "scooter-12": {"x":204,"y":528,"width":12,"height":12},
18908         "gift-24": {"x":216,"y":528,"width":24,"height":24},
18909         "gift-18": {"x":240,"y":528,"width":18,"height":18},
18910         "gift-12": {"x":258,"y":528,"width":12,"height":12},
18911         "ice-cream-24": {"x":0,"y":552,"width":24,"height":24},
18912         "ice-cream-18": {"x":24,"y":552,"width":18,"height":18},
18913         "ice-cream-12": {"x":42,"y":552,"width":12,"height":12}
18914 };
18915
18916 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}}};
18917 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}}};
18918 var dataSuggestions = {
18919         amenity: amenity,
18920         shop: shop
18921 };
18922
18923 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"]]}];
18924
18925 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"}}];
18926
18927 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"];
18928
18929 var dataLocales = {"af":{"rtl":false},"ar":{"rtl":true},"ar-AA":{"rtl":true},"ast":{"rtl":false},"bg-BG":{"rtl":false},"bn":{"rtl":false},"bs":{"rtl":false},"ca":{"rtl":false},"cs":{"rtl":false},"da":{"rtl":false},"de":{"rtl":false},"el":{"rtl":false},"en-GB":{"rtl":false},"eo":{"rtl":false},"es":{"rtl":false},"et":{"rtl":false},"fa":{"rtl":true},"fi":{"rtl":false},"fr":{"rtl":false},"gl":{"rtl":false},"gu":{"rtl":false},"hi":{"rtl":false},"hr":{"rtl":false},"hu":{"rtl":false},"hy":{"rtl":false},"id":{"rtl":false},"is":{"rtl":false},"it":{"rtl":false},"ja":{"rtl":false},"kn":{"rtl":false},"ko":{"rtl":false},"ku":{"rtl":false},"lij":{"rtl":false},"lt":{"rtl":false},"lv":{"rtl":false},"ml":{"rtl":false},"nl":{"rtl":false},"no":{"rtl":false},"pl":{"rtl":false},"pt":{"rtl":false},"pt-BR":{"rtl":false},"ro":{"rtl":false},"ru":{"rtl":false},"sc":{"rtl":false},"si":{"rtl":false},"sk":{"rtl":false},"sl":{"rtl":false},"sq":{"rtl":false},"sr":{"rtl":false},"sv":{"rtl":false},"ta":{"rtl":false},"te":{"rtl":false},"th":{"rtl":false},"tl":{"rtl":false},"tr":{"rtl":false},"uk":{"rtl":false},"vi":{"rtl":false},"yue":{"rtl":false},"zh":{"rtl":false},"zh-CN":{"rtl":false},"zh-HK":{"rtl":false},"zh-TW":{"rtl":false}};
18930
18931 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"};
18932
18933 var type = "FeatureCollection";
18934 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]]]}}];
18935 var dataImperial = {
18936         type: type,
18937         features: features
18938 };
18939
18940 var type$1 = "FeatureCollection";
18941 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]]]}}];
18942 var dataDriveLeft = {
18943         type: type$1,
18944         features: features$1
18945 };
18946
18947 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"},"bath/open_air":{"label":"Open Air"},"bath/sand_bath":{"label":"Sand Bath"},"bath/type":{"label":"Specialty","options":{"onsen":"Japanese Onsen","foot_bath":"Foot Bath","hot_spring":"Hot Spring"}},"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"},"camera/direction":{"label":"Direction (Degrees Clockwise)","placeholder":"45, 90, 180, 270"},"camera/mount":{"label":"Camera Mount"},"camera/type":{"label":"Camera Type","options":{"fixed":"Fixed","panning":"Panning","dome":"Dome"}},"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"},"contact/webcam":{"label":"Webcam URL","placeholder":"http://example.com/"},"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"},"fence_type":{"label":"Type"},"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"},"internet_access/ssid":{"label":"SSID (Network Name)"},"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"},"maxheight":{"label":"Max Height","placeholder":"4, 4.5, 5, 14'0\", 14'6\", 15'0\""},"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"},"outdoor_seating":{"label":"Outdoor Seating"},"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"},"surveillance":{"label":"Surveillance Kind"},"surveillance/type":{"label":"Surveillance Type","options":{"camera":"Camera","guard":"Guard","ALPR":"Automatic License Plate Reader"}},"surveillance/zone":{"label":"Surveillance Zone"},"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)"}},"wall":{"label":"Type"},"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/crematorium":{"name":"Crematorium","terms":"cemetery,funeral"},"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/food_court":{"name":"Food Court","terms":"fast food,restaurant,food"},"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":"game,lookout,shoot,wild,watch"},"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":"alcohol,drink,dive,beer,bier,booze"},"amenity/public_bath":{"name":"Public Bath","terms":"onsen,foot bath,hot springs"},"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_mirror":{"name":"Traffic Mirror","terms":"blind spot,convex,corner,curved,roadside,round,safety,sphere,visibility"},"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/dance":{"name":"Dance Hall","terms":"ballroom,jive,swing,tango,waltz"},"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/resort":{"name":"Resort","terms":""},"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_camera":{"name":"Surveillance Camera","terms":"anpr,alpr,camera,car plate recognition,cctv,guard,license plate recognition,monitoring,number plate recognition,security,video,webcam"},"man_made/surveillance":{"name":"Surveillance","terms":"anpr,alpr,camera,car plate recognition,cctv,guard,license plate recognition,monitoring,number plate recognition,security,video,webcam"},"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/aquarium":{"name":"Aquarium","terms":"fish,sea,water"},"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":"animal"},"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/waterfall":{"name":"Waterfall","terms":"fall"},"waterway/weir":{"name":"Weir","terms":""}}}};
18948
18949 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":[[[-122.98339348286,48.78214357977],[-122.93498497456,48.76653172572],[-122.91181068867,48.73857664785],[-122.80229073018,48.73982194177],[-122.81945686787,48.75498940888],[-122.93429832906,48.79571515892],[-122.98373680562,48.79435816618],[-122.98339348286,48.78214357977]],[[-123.02167396992,48.44667085335],[-122.9466579482,48.44780949945],[-122.90151100606,48.41306930778],[-122.80263405293,48.40771378918],[-122.79199104756,48.44279926564],[-122.8088138625,48.47865708877],[-122.73911934346,48.49572334021],[-122.78546791524,48.62160819278],[-122.73087959737,48.6361306644],[-122.75559883565,48.71207854113],[-122.95747261494,48.71592956034],[-122.97086220235,48.695765074],[-122.99970131367,48.69780454658],[-123.00347786397,48.73427448605],[-123.04330330342,48.74310484148],[-123.0762622878,48.70528190578],[-123.08484535664,48.66334903433],[-123.12844734639,48.66380254936],[-123.22698097676,48.70301615666],[-123.24655037373,48.68352650341],[-123.17445259541,48.64701977542],[-123.21513634175,48.60106537642],[-123.21393471211,48.57335906966],[-123.18080406636,48.56574853208],[-123.16621284932,48.52006125122],[-123.10235481709,48.47683634964],[-123.02167396992,48.44667085335]]],"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.","scaleExtent":[0,19],"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.","scaleExtent":[0,19],"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":"GRB","name":"Belgium AGIV GRB Flanders","type":"tms","template":"http://tile.informatievlaanderen.be/ws/raadpleegdiensten/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=grb_bsk&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":"GRB Flanders (c) AGIV"},{"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":"CRAIG-Auvergne-2013","name":"CRAIG - Auvergne 2013 - 25 cm","type":"tms","template":"http://tiles.craig.fr/osm/tms/1.0.0/ortho_2013/webmercator/{zoom-1}/{x}/{-y}.jpeg","polygon":[[[2.9401192,44.6338837],[2.9971896,44.633931],[2.9971676,44.6473385],[3.0159744,44.6473541],[3.0159305,44.6741168],[3.0349486,44.6741326],[3.0349036,44.7015216],[3.0536338,44.7015371],[3.0535675,44.7418954],[3.0723301,44.741911],[3.0722196,44.8091687],[3.0921583,44.8091852],[3.092137,44.8221252],[3.1301398,44.8221567],[3.1300495,44.8770722],[3.1485587,44.8770875],[3.1485807,44.8636964],[3.1682313,44.8637126],[3.1682538,44.8500261],[3.2064,44.8500576],[3.2063789,44.8628393],[3.2439492,44.8628704],[3.2439263,44.8767893],[3.2631452,44.8768052],[3.2630782,44.9175197],[3.3200437,44.9175667],[3.3200227,44.9303336],[3.3390815,44.9303493],[3.3390586,44.9441978],[3.3769989,44.9442292],[3.3770218,44.9302879],[3.396031,44.9303036],[3.39612,44.8762713],[3.4148252,44.8762867],[3.4148923,44.8355255],[3.4333371,44.8355408],[3.4333819,44.8082784],[3.4525549,44.8082943],[3.4525774,44.7946344],[3.5089262,44.7946811],[3.508904,44.8081469],[3.604265,44.8082258],[3.6042213,44.8348239],[3.6236136,44.83484],[3.6235695,44.8616583],[3.6424823,44.8616739],[3.642549,44.821102],[3.6610055,44.8211172],[3.6610275,44.8077696],[3.6992999,44.8078013],[3.6992782,44.820994],[3.7361139,44.8210245],[3.7361819,44.7797075],[3.7751058,44.7797397],[3.775151,44.7522344],[3.8118352,44.7522648],[3.8118567,44.7392021],[3.8311822,44.7392181],[3.8312061,44.7246766],[3.887824,44.7247235],[3.8878019,44.7381833],[3.925626,44.7382146],[3.9256039,44.7516682],[3.9454097,44.7516846],[3.9453656,44.7784691],[3.9643737,44.7784848],[3.9643516,44.7919273],[4.0033183,44.7919596],[4.0032964,44.8052575],[4.0216937,44.8052727],[4.0216718,44.8185687],[4.0596515,44.8186001],[4.0596082,44.8449216],[4.0798132,44.8449383],[4.0797928,44.8573502],[4.173882,44.857428],[4.1738604,44.8705468],[4.1932576,44.8705628],[4.193235,44.8842744],[4.2140385,44.8842916],[4.2139961,44.9100242],[4.2324138,44.9100394],[4.2323689,44.9373093],[4.2715486,44.9373416],[4.2715273,44.9502971],[4.3288672,44.9503445],[4.3287793,45.0036659],[4.3489259,45.0036825],[4.3489038,45.0170656],[4.4060793,45.0171127],[4.4059904,45.0710024],[4.3884707,45.0709879],[4.3884482,45.0845976],[4.407943,45.0846137],[4.4079231,45.09663],[4.4843608,45.0966929],[4.4842941,45.1370472],[4.4663631,45.1370324],[4.4663413,45.1502035],[4.4864469,45.15022],[4.4864022,45.1772415],[4.5065524,45.177258],[4.5064402,45.2450058],[4.4881342,45.2449908],[4.4881106,45.2592077],[4.4698588,45.2591927],[4.469836,45.2729835],[4.4508849,45.2729679],[4.4508626,45.2864203],[4.3936753,45.2863733],[4.3936303,45.3135182],[4.3750893,45.3135029],[4.3750662,45.3274054],[4.3950734,45.3274218],[4.3950283,45.3545849],[4.3767871,45.35457],[4.3767639,45.3685486],[4.3576564,45.3685329],[4.3576335,45.3823359],[4.2814576,45.3822734],[4.2814334,45.3968834],[4.2444556,45.3968531],[4.2444325,45.4107893],[4.1481178,45.4107104],[4.1481388,45.3980659],[4.1291913,45.3980504],[4.1292145,45.3840899],[4.0902138,45.3840579],[4.0902351,45.3712093],[4.0135507,45.3711464],[4.0135259,45.3860975],[3.9170932,45.3860185],[3.9170704,45.3997355],[3.9375703,45.3997523],[3.9375481,45.4131142],[3.975277,45.4131451],[3.9752552,45.4262061],[3.9953725,45.4262226],[3.9956999,45.5209568],[3.9777821,45.5209421],[3.977693,45.5743873],[3.9581755,45.5743714],[3.9581522,45.5883658],[3.9396019,45.5883506],[3.9395781,45.6026212],[3.9202279,45.6026054],[3.9202048,45.6164603],[3.8818916,45.616429],[3.8818468,45.643276],[3.8441329,45.6432453],[3.8441098,45.6570896],[3.8261689,45.657075],[3.8261241,45.6838865],[3.8072175,45.6838711],[3.8071277,45.7375802],[3.7882101,45.7375648],[3.7881863,45.7517966],[3.7688482,45.7517809],[3.7688028,45.7789651],[3.750719,45.7789504],[3.7505822,45.8606554],[3.7696692,45.8606709],[3.7695793,45.914333],[3.751661,45.9143185],[3.7516379,45.9280879],[3.7328974,45.9280727],[3.7328527,45.9547155],[3.8101795,45.9547782],[3.8101569,45.9682278],[3.8495994,45.9682598],[3.8495098,46.0216192],[3.8318849,46.0216049],[3.8317936,46.0759058],[3.8505037,46.0759209],[3.8504583,46.1029545],[3.8324727,46.10294],[3.8323353,46.1845598],[3.8142194,46.1845452],[3.8141522,46.2244234],[3.8336864,46.2244392],[3.8336634,46.2381001],[3.8528929,46.2381156],[3.8528703,46.2514729],[3.8931424,46.2515054],[3.8931205,46.2644677],[3.9130562,46.2644838],[3.9130335,46.2779317],[3.9518926,46.2779631],[3.9518709,46.2908227],[3.971523,46.2908386],[3.9715012,46.3036947],[4.0105021,46.3037261],[4.0104784,46.3177638],[4.0298278,46.3177794],[4.029783,46.3442827],[4.0116018,46.344268],[4.0114647,46.4253437],[4.031532,46.4253598],[4.0314635,46.4657978],[4.0132435,46.4657832],[4.0132204,46.479378],[3.9943703,46.4793629],[3.9943461,46.4936113],[3.9745971,46.4935955],[3.9745735,46.5075278],[3.8775423,46.5074499],[3.8774959,46.5347758],[3.8583577,46.5347605],[3.8583347,46.5483156],[3.8186897,46.5482838],[3.8187114,46.5355316],[3.7992386,46.535516],[3.7992156,46.5490706],[3.7610377,46.5490399],[3.7609226,46.6168059],[3.7423295,46.616791],[3.7422834,46.6439624],[3.7228558,46.6439468],[3.7228098,46.6710357],[3.7038706,46.6710206],[3.7038474,46.6846709],[3.6841096,46.6846551],[3.6840631,46.711998],[3.6648359,46.7119826],[3.6647898,46.7390375],[3.6457623,46.7390222],[3.6457158,46.7663375],[3.6257542,46.7663216],[3.6257314,46.7797093],[3.5672301,46.7796626],[3.5672528,46.7663082],[3.5471462,46.7662922],[3.5471922,46.7392824],[3.5271621,46.7392664],[3.5272308,46.6988967],[3.4877399,46.6988651],[3.4877618,46.685943],[3.4679636,46.6859272],[3.4679407,46.6994059],[3.4679179,46.7127907],[3.4486497,46.7127753],[3.4486258,46.7267878],[3.350433,46.7267092],[3.3504786,46.6999004],[3.3303913,46.6998843],[3.3303448,46.7271984],[3.2327174,46.7271203],[3.2327406,46.7135148],[3.2129042,46.7134989],[3.212927,46.7001302],[3.1735446,46.7000987],[3.173498,46.7275094],[3.1541227,46.7274939],[3.1541002,46.7407271],[3.1147772,46.7406957],[3.114754,46.7542756],[3.0753432,46.7542441],[3.0752971,46.7813548],[3.05597,46.7813394],[3.055924,46.8083069],[2.99704,46.8082598],[2.9970166,46.8219593],[2.9379443,46.8219121],[2.9379675,46.8082604],[2.8986634,46.808229],[2.8986872,46.7942392],[2.878991,46.7942234],[2.8790134,46.7810427],[2.8594188,46.781027],[2.8594415,46.7677056],[2.8400446,46.7676901],[2.8400671,46.754466],[2.7414032,46.7543871],[2.741382,46.7668245],[2.7023351,46.7667932],[2.7023571,46.7538869],[2.6826621,46.7538711],[2.6826849,46.7404752],[2.6634875,46.7404599],[2.6635123,46.7258966],[2.6434164,46.7258805],[2.6434382,46.7130938],[2.6241432,46.7130784],[2.6241658,46.6998093],[2.6039699,46.6997931],[2.6039936,46.6858433],[2.5651245,46.6858122],[2.5651469,46.6726126],[2.5459278,46.6725972],[2.5459966,46.6321534],[2.5659222,46.6321694],[2.565946,46.6181104],[2.5456397,46.6180941],[2.5456862,46.5907192],[2.5664225,46.5907358],[2.5664449,46.5775417],[2.5854963,46.577557],[2.5855181,46.5647199],[2.5661318,46.5647044],[2.5661557,46.5506246],[2.468279,46.5505461],[2.4683039,46.5358205],[2.3321246,46.5357112],[2.3321701,46.5088566],[2.3126474,46.5088409],[2.3126703,46.4953444],[2.2928767,46.4953285],[2.2928996,46.4818182],[2.2748687,46.4818037],[2.2749151,46.4544154],[2.2553921,46.4543997],[2.255529,46.3734888],[2.275948,46.3735052],[2.276037,46.3208741],[2.3145615,46.3209052],[2.3145849,46.3070421],[2.3537075,46.3070737],[2.3537313,46.2929669],[2.3938428,46.2929992],[2.3938862,46.2672854],[2.4515727,46.267332],[2.451596,46.2534921],[2.4709353,46.2535077],[2.4709807,46.2265552],[2.4915062,46.2265718],[2.4915521,46.199329],[2.5108806,46.1993446],[2.5109254,46.1727799],[2.5311728,46.1727963],[2.5313772,46.051352],[2.5516349,46.0513684],[2.5516577,46.0377665],[2.5705635,46.0377818],[2.5706774,45.9699434],[2.5514356,45.9699278],[2.551458,45.9566151],[2.5322621,45.9565995],[2.5322849,45.9430066],[2.5130653,45.942991],[2.513134,45.9020279],[2.4749412,45.9019969],[2.4749633,45.8888235],[2.4361947,45.888792],[2.4362172,45.8753288],[2.417209,45.8753133],[2.4172548,45.8479368],[2.3784736,45.8479053],[2.378497,45.8339746],[2.3595157,45.8339592],[2.3595606,45.8070849],[2.3787254,45.8071005],[2.3787481,45.7935783],[2.3986981,45.7935945],[2.3987203,45.7803477],[2.4182486,45.7803636],[2.4183161,45.7400007],[2.4572171,45.7400324],[2.4572394,45.7266956],[2.4758919,45.7267107],[2.4759144,45.7132391],[2.49533,45.7132549],[2.4954204,45.6591268],[2.4576942,45.659096],[2.4577622,45.618343],[2.4391188,45.6183278],[2.4391866,45.5776619],[2.4585044,45.5776777],[2.4585496,45.5505348],[2.4780887,45.5505508],[2.4781108,45.5372464],[2.4975506,45.5372623],[2.4975949,45.5106757],[2.4785536,45.5106601],[2.4786444,45.4561337],[2.4597798,45.4561183],[2.4598701,45.401757],[2.4224876,45.4017264],[2.4224651,45.4152816],[2.4023154,45.4152651],[2.4022929,45.4288193],[2.3256006,45.4287565],[2.3256684,45.3879609],[2.3456182,45.3879773],[2.3456629,45.3611091],[2.326256,45.3610932],[2.326279,45.3472146],[2.3073819,45.3471991],[2.3074045,45.3335972],[2.2881095,45.3335813],[2.2881307,45.3208191],[2.2696332,45.3208039],[2.2696574,45.306212],[2.2506602,45.3061964],[2.2506828,45.2925147],[2.2316866,45.2924992],[2.2317086,45.2792355],[2.2130009,45.2792202],[2.213046,45.2520355],[2.1937387,45.2520197],[2.1937617,45.2381134],[2.1756091,45.2380985],[2.1757423,45.1576822],[2.1573543,45.157667],[2.1574448,45.1029478],[2.1202408,45.1029172],[2.1202629,45.0895468],[2.1006669,45.0895306],[2.1006902,45.0754441],[2.0824591,45.0754291],[2.082548,45.0215961],[2.1025534,45.0216126],[2.1025982,44.994453],[2.0457406,44.9944061],[2.0458508,44.9275321],[2.0657794,44.9275486],[2.0658912,44.8596881],[2.0856964,44.8597044],[2.0857193,44.8458126],[2.1055593,44.8458291],[2.1056029,44.8193264],[2.124743,44.8193422],[2.1247657,44.805512],[2.1435067,44.8055275],[2.143551,44.778597],[2.1256091,44.7785822],[2.1256984,44.7242739],[2.1066459,44.7242581],[2.1067116,44.6842263],[2.1263414,44.6842426],[2.1263635,44.670735],[2.14598,44.6707513],[2.146069,44.6164441],[2.1839622,44.6164756],[2.183983,44.6037819],[2.2404173,44.6038288],[2.2403728,44.6309515],[2.25948,44.6309674],[2.2594571,44.644934],[2.316678,44.6449815],[2.3167011,44.6308801],[2.3361516,44.6308963],[2.3361734,44.6175824],[2.3724238,44.6176125],[2.3724009,44.6315823],[2.4110495,44.6316144],[2.4110701,44.6190741],[2.4492173,44.6191058],[2.4491956,44.6323197],[2.5048575,44.6323659],[2.5048126,44.6597555],[2.5246119,44.6597719],[2.524567,44.6871739],[2.5422544,44.6871886],[2.5422313,44.70122],[2.5807101,44.701252],[2.5805999,44.7683374],[2.61769,44.7683681],[2.6176235,44.808838],[2.6367564,44.8088539],[2.6366899,44.8492948],[2.6733105,44.8493251],[2.6732888,44.8625164],[2.6933766,44.862533],[2.6933323,44.8894303],[2.7305201,44.8894611],[2.7304757,44.9164461],[2.7499202,44.9164622],[2.7500519,44.8364688],[2.8073346,44.8365162],[2.8073139,44.8491017],[2.8263796,44.8491175],[2.8264007,44.8362845],[2.8457039,44.8363004],[2.8457707,44.7957107],[2.8642166,44.795726],[2.8642611,44.7686452],[2.8839885,44.7686615],[2.8840323,44.7419697],[2.9020315,44.7419846],[2.9021426,44.6743192],[2.9219777,44.6743357],[2.9220221,44.6472986],[2.9400972,44.6473136],[2.9401192,44.6338837]]],"terms_url":"http://wiki.openstreetmap.org/wiki/WikiProject_France/CRAIG","terms_text":"Orthophotographie CRAIG/Sintegra/IGN 2013"},{"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]]],"terms_url":"https://firstmap.delaware.gov/arcgis/rest/services/DE_Imagery/DE_Imagery_2012/ImageServer","terms_text":"Digital Aerial Solutions, LLC"},{"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":"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":"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":[4,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","best":true},{"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":"https://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":"https://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":"https://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":"NLSC-EMAP5","name":"NLSC General Map with Contour line","type":"tms","template":"http://maps.nlsc.gov.tw/S_Maps/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=EMAP5_OPENDATA&STYLE=_null&TILEMATRIXSET=EPSG:3857&TILEMATRIX=EPSG:3857:{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image/png","description":"The emap from Taiwan National Land Surveying and Mapping Center","scaleExtent":[0,15],"polygon":[[[120.4570579,26.3970586],[120.44256,26.3708009],[120.44713,26.3531513],[120.4673009,26.3405831],[120.4978723,26.3340866],[120.5141036,26.3401594],[120.5341168,26.3641649],[120.5297045,26.3842128],[120.4956661,26.4015754],[120.4570579,26.3970586]],[[119.9007221,25.9858609],[119.8960071,25.9648902],[119.9131301,25.9470399],[119.9503542,25.9278478],[119.9905563,25.9260623],[120.0198392,25.9363284],[120.0277804,25.9557423],[120.0275322,25.9845224],[119.9989937,26.0010288],[119.9404278,26.0028131],[119.9007221,25.9858609]],[[122.089,24.5485],[121.709,23.4541],[121.717,22.698],[121.818,21.95],[121.803,21.8735],[121.759,21.8087],[121.694,21.7653],[120.861,21.5631],[120.815,21.5576],[120.739,21.5728],[120.661,21.6296],[120.202,22.1809],[119.27,23.0542],[119.153,23.2049],[119.128,23.2485],[119.103,23.4],[119.118,23.4765],[119.137,23.512],[119.361,23.8885],[119.406,23.9407],[120.968,25.2284],[121.408,25.4687],[121.989,25.8147],[122.065,25.8299],[122.141,25.8147],[122.216,25.7663],[122.26,25.7015],[122.297,25.48],[122.196,24.9696],[122.089,24.5485]],[[116.6855033,20.8547596],[116.6309071,20.8149565],[116.5941695,20.7600846],[116.5797214,20.6967501],[116.5893056,20.6325865],[116.621766,20.5753367],[116.6731874,20.5319171],[116.7373678,20.5075783],[116.8065659,20.5052653],[116.8724354,20.5252581],[116.9270316,20.5651373],[116.9637692,20.6200797],[116.9782173,20.6834462],[116.9686331,20.7475883],[116.9361727,20.8047732],[116.8847512,20.8481147],[116.8205709,20.872399],[116.7513728,20.8747063],[116.6855033,20.8547596]],[[118.2261504,24.4563345],[118.2936439,24.4538527],[118.2851467,24.4751026],[118.3097372,24.4916821],[118.3767709,24.4729348],[118.4100947,24.5332285],[118.4479031,24.5284069],[118.4746394,24.4599272],[118.512992,24.4315479],[118.5065839,24.4202318],[118.4811625,24.4332439],[118.4610567,24.4089192],[118.426145,24.3970385],[118.3970055,24.4284184],[118.3765564,24.4258395],[118.3397565,24.3814628],[118.3031926,24.3705764],[118.2574234,24.4139213],[118.1381276,24.3724838],[118.1617342,24.4022433],[118.2094226,24.4139604],[118.1895784,24.4352201],[118.2176338,24.430205],[118.2261504,24.4563345]],[[120.2234496,26.30045],[120.2550843,26.3100412],[120.269888,26.3368716],[120.2591889,26.3652192],[120.2292544,26.3784823],[120.1976197,26.3688968],[120.182816,26.3420738],[120.1935151,26.3137205],[120.2234496,26.30045]],[[119.4374461,25.0047541],[119.4342024,24.9886249],[119.4541901,24.9722553],[119.4827444,24.9718376],[119.4898402,24.9937882],[119.4715877,25.0069239],[119.4374461,25.0047541]],[[119.8869914,26.180381],[119.893227,26.1203128],[119.9285109,26.1080224],[119.9779388,26.1223611],[120.0366775,26.151728],[120.1098054,26.2134921],[120.119269,26.2713663],[120.0629175,26.3172592],[119.9923706,26.3164881],[119.9467732,26.2898799],[119.9020362,26.2439761],[119.8869914,26.180381]]],"terms_url":"http://maps.nlsc.gov.tw/","terms_text":"NLSC EMAP 2015"},{"id":"MAPNIK","name":"OpenStreetMap (Standard)","type":"tms","template":"https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png","description":"The default OpenStreetMap layer.","scaleExtent":[0,19],"terms_url":"https://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","best":true},{"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"}];
18950
18951 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"],"fields":["ref","iata","icao","operator","internet_access","internet_access/fee","internet_access/ssid"],"terms":["airplane","airport","aerodrome"],"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","outdoor_seating"],"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","outdoor_seating"],"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","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"tags":{"amenity":"bus_station"},"name":"Bus Station"},"amenity/cafe":{"icon":"cafe","fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"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","internet_access","internet_access/ssid"],"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","internet_access","internet_access/fee","internet_access/ssid"],"geometry":["point","area"],"terms":["coworking","office"],"tags":{"amenity":"coworking_space"},"name":"Coworking Space"},"amenity/crematorium":{"icon":"cemetery","fields":["website","phone","opening_hours","wheelchair"],"geometry":["area","point"],"tags":{"amenity":"crematorium"},"terms":["cemetery","funeral"],"name":"Crematorium"},"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","outdoor_seating"],"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/food_court":{"icon":"restaurant","fields":["operator","address","building_area","opening_hours","smoking","outdoor_seating"],"geometry":["point","area"],"terms":["fast food","restaurant","food"],"tags":{"amenity":"food_court"},"name":"Food Court"},"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":["game","lookout","shoot","wild","watch"],"tags":{"amenity":"hunting_stand"},"name":"Hunting Stand"},"amenity/ice_cream":{"icon":"ice-cream","fields":["address","building_area","opening_hours","takeaway","delivery","outdoor_seating"],"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","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"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","internet_access","internet_access/fee","internet_access/ssid"],"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","outdoor_seating"],"geometry":["point","area"],"tags":{"amenity":"pub"},"terms":["alcohol","drink","dive","beer","bier","booze"],"name":"Pub"},"amenity/public_bath":{"icon":"water","fields":["bath/type","bath/open_air","bath/sand_bath","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"public_bath"},"terms":["onsen","foot bath","hot springs"],"name":"Public Bath"},"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","outdoor_seating"],"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","internet_access","internet_access/fee","internet_access/ssid"],"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","internet_access","internet_access/ssid"],"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","matchScore":0.4},"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","fields":["height"],"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","matchScore":0.25},"barrier/fence":{"icon":"prison","fields":["fence_type","height"],"geometry":["line"],"tags":{"barrier":"fence"},"name":"Fence","matchScore":0.25},"barrier/gate":{"icon":"prison","fields":["access"],"geometry":["point","vertex","line"],"tags":{"barrier":"gate"},"name":"Gate"},"barrier/hedge":{"fields":["height"],"geometry":["line","area"],"tags":{"barrier":"hedge"},"name":"Hedge","matchScore":0.25},"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","fields":["wall","height"],"geometry":["line","area"],"tags":{"barrier":"wall"},"name":"Wall","matchScore":0.25},"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.6,"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"],"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","lanes","surface","maxheight","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","lanes","surface","maxheight","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","maxheight","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","lanes","surface","maxheight","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","maxheight","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","lanes","surface","maxheight","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","lanes","surface","maxheight"],"geometry":["line"],"tags":{"highway":"road"},"terms":[],"name":"Unknown Road"},"highway/secondary_link":{"icon":"highway-secondary-link","fields":["oneway","maxspeed","structure","access","lanes","surface","maxheight","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","maxheight","ref","cycleway"],"geometry":["line"],"tags":{"highway":"secondary"},"terms":[],"name":"Secondary Road"},"highway/service":{"icon":"highway-service","fields":["service","oneway","maxspeed","structure","access","surface","maxheight"],"geometry":["line"],"tags":{"highway":"service"},"terms":[],"name":"Service Road"},"highway/service/alley":{"icon":"highway-service","fields":["oneway","maxspeed","structure","access","surface","maxheight"],"geometry":["line"],"tags":{"highway":"service","service":"alley"},"name":"Alley"},"highway/service/drive-through":{"icon":"highway-service","fields":["oneway","maxspeed","structure","access","surface","maxheight"],"geometry":["line"],"tags":{"highway":"service","service":"drive-through"},"name":"Drive-Through"},"highway/service/driveway":{"icon":"highway-service","fields":["oneway","maxspeed","structure","access","surface","maxheight"],"geometry":["line"],"tags":{"highway":"service","service":"driveway"},"name":"Driveway"},"highway/service/emergency_access":{"icon":"highway-service","fields":["oneway","maxspeed","structure","access","surface","maxheight"],"geometry":["line"],"tags":{"highway":"service","service":"emergency_access"},"name":"Emergency Access"},"highway/service/parking_aisle":{"icon":"highway-service","fields":["oneway","maxspeed","structure","access","surface","maxheight"],"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","lanes","surface","maxheight","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","maxheight","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_mirror":{"geometry":["point"],"tags":{"highway":"traffic_mirror"},"terms":["blind spot","convex","corner","curved","roadside","round","safety","sphere","visibility"],"name":"Traffic Mirror"},"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","lanes","surface","maxheight","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","maxheight","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","lanes","surface","maxheight","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/dance":{"fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["ballroom","jive","swing","tango","waltz"],"tags":{"leisure":"dance"},"name":"Dance Hall"},"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","internet_access/fee","internet_access/ssid"],"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/resort":{"fields":["operator","address","opening_hours"],"geometry":["point","area"],"tags":{"leisure":"resort"},"name":"Resort"},"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_camera":{"icon":"camera","geometry":["point"],"fields":["surveillance","surveillance/type","camera/type","camera/mount","camera/direction","surveillance/zone","contact/webcam"],"terms":["anpr","alpr","camera","car plate recognition","cctv","guard","license plate recognition","monitoring","number plate recognition","security","video","webcam"],"tags":{"man_made":"surveillance","surveillance:type":"camera"},"name":"Surveillance Camera"},"man_made/surveillance":{"icon":"camera","geometry":["point"],"fields":["surveillance","surveillance/type","surveillance/zone"],"terms":["anpr","alpr","camera","car plate recognition","cctv","guard","license plate recognition","monitoring","number plate recognition","security","video","webcam"],"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","internet_access","internet_access/fee","internet_access/ssid"],"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","internet_access","internet_access/fee","internet_access/ssid"],"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","internet_access","internet_access/fee","internet_access/ssid"],"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","internet_access/ssid"],"geometry":["point","area"],"tags":{"tourism":"apartment"},"name":"Guest Apartment / Condo"},"tourism/aquarium":{"icon":"water","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["fish","sea","water"],"tags":{"tourism":"aquarium"},"name":"Aquarium"},"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","internet_access","internet_access/fee","internet_access/ssid"],"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","internet_access/fee","internet_access/ssid"],"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","internet_access","internet_access/fee","internet_access/ssid"],"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","internet_access/ssid"],"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","internet_access/ssid"],"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","internet_access/ssid"],"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","internet_access/ssid"],"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"],"terms":["animal"],"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/waterfall":{"icon":"water","fields":["height","width"],"geometry":["vertex"],"terms":["fall"],"tags":{"waterway":"waterfall"},"name":"Waterfall"},"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","outdoor_seating"],"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","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Cafeteria":{"tags":{"name":"Cafeteria","amenity":"cafe"},"name":"Cafeteria","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Costa":{"tags":{"name":"Costa","amenity":"cafe"},"name":"Costa","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Caffè Nero":{"tags":{"name":"Caffè Nero","amenity":"cafe"},"name":"Caffè Nero","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Кафе":{"tags":{"name":"Кафе","amenity":"cafe"},"name":"Кафе","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Café Central":{"tags":{"name":"Café Central","amenity":"cafe"},"name":"Café Central","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Second Cup":{"tags":{"name":"Second Cup","amenity":"cafe"},"name":"Second Cup","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Dunkin Donuts":{"tags":{"name":"Dunkin Donuts","cuisine":"donut","amenity":"cafe"},"name":"Dunkin Donuts","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Espresso House":{"tags":{"name":"Espresso House","amenity":"cafe"},"name":"Espresso House","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Segafredo":{"tags":{"name":"Segafredo","amenity":"cafe"},"name":"Segafredo","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Coffee Time":{"tags":{"name":"Coffee Time","amenity":"cafe"},"name":"Coffee Time","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"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","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Eiscafe Venezia":{"tags":{"name":"Eiscafe Venezia","amenity":"cafe"},"name":"Eiscafe Venezia","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/スターバックス":{"tags":{"name":"スターバックス","name:en":"Starbucks","amenity":"cafe"},"name":"スターバックス","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Шоколадница":{"tags":{"name":"Шоколадница","amenity":"cafe"},"name":"Шоколадница","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"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","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Столовая":{"tags":{"name":"Столовая","amenity":"cafe"},"name":"Столовая","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/ドトール":{"tags":{"name":"ドトール","name:en":"DOUTOR","amenity":"cafe"},"name":"ドトール","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Tchibo":{"tags":{"name":"Tchibo","amenity":"cafe"},"name":"Tchibo","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Кофе Хауз":{"tags":{"name":"Кофе Хауз","amenity":"cafe"},"name":"Кофе Хауз","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Caribou Coffee":{"tags":{"name":"Caribou Coffee","amenity":"cafe"},"name":"Caribou Coffee","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Уют":{"tags":{"name":"Уют","amenity":"cafe"},"name":"Уют","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Шашлычная":{"tags":{"name":"Шашлычная","amenity":"cafe"},"name":"Шашлычная","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/คาเฟ่ อเมซอน":{"tags":{"name":"คาเฟ่ อเมซอน","amenity":"cafe"},"name":"คาเฟ่ อเมซอน","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"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","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/カフェ・ド・クリエ":{"tags":{"name":"カフェ・ド・クリエ","name:en":"Cafe de CRIE","amenity":"cafe"},"name":"カフェ・ド・クリエ","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"suggestion":true},"amenity/cafe/Cafe Amazon":{"tags":{"name":"Cafe Amazon","amenity":"cafe"},"name":"Cafe Amazon","icon":"cafe","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid","smoking","outdoor_seating"],"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","internet_access","internet_access/fee","internet_access/ssid"],"suggestion":true},"shop/books/Waterstones":{"tags":{"name":"Waterstones","shop":"books"},"name":"Waterstones","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"suggestion":true},"shop/books/Libro":{"tags":{"name":"Libro","shop":"books"},"name":"Libro","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"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","internet_access","internet_access/fee","internet_access/ssid"],"suggestion":true},"shop/books/Weltbild":{"tags":{"name":"Weltbild","shop":"books"},"name":"Weltbild","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"suggestion":true},"shop/books/Thalia":{"tags":{"name":"Thalia","shop":"books"},"name":"Thalia","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"suggestion":true},"shop/books/Книги":{"tags":{"name":"Книги","shop":"books"},"name":"Книги","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","internet_access","internet_access/fee","internet_access/ssid"],"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}};
18952
18953 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"]};
18954
18955 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"]}};
18956
18957 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"},"bath/open_air":{"key":"bath:open_air","label":"Open Air","type":"check"},"bath/sand_bath":{"key":"bath:sand_bath","label":"Sand Bath","type":"check"},"bath/type":{"key":"bath:type","type":"combo","label":"Specialty","strings":{"options":{"onsen":"Japanese Onsen","foot_bath":"Foot Bath","hot_spring":"Hot Spring"}}},"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"},"camera/direction":{"key":"camera:direction","type":"number","label":"Direction (Degrees Clockwise)","placeholder":"45, 90, 180, 270"},"camera/mount":{"key":"camera:mount","type":"combo","label":"Camera Mount"},"camera/type":{"key":"camera:type","type":"combo","label":"Camera Type","strings":{"options":{"fixed":"Fixed","panning":"Panning","dome":"Dome"}}},"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"},"contact/webcam":{"key":"contact:webcam","type":"url","icon":"website","label":"Webcam URL","placeholder":"http://example.com/"},"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"},"fence_type":{"key":"fence_type","type":"combo","label":"Type"},"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"},"internet_access/ssid":{"key":"internet_access:ssid","type":"text","label":"SSID (Network Name)"},"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"},"maxheight":{"key":"maxheight","type":"combo","label":"Max Height","placeholder":"4, 4.5, 5, 14'0\", 14'6\", 15'0\"","snake_case":false},"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"},"outdoor_seating":{"key":"outdoor_seating","type":"combo","label":"Outdoor Seating"},"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"},"surveillance":{"key":"surveillance","type":"combo","label":"Surveillance Kind"},"surveillance/type":{"key":"surveillance:type","type":"combo","label":"Surveillance Type","strings":{"options":{"camera":"Camera","guard":"Guard","ALPR":"Automatic License Plate Reader"}}},"surveillance/zone":{"key":"surveillance:zone","type":"combo","label":"Surveillance Zone"},"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)"}}},"wall":{"key":"wall","type":"combo","label":"Type"},"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"}};
18958
18959 var data = {
18960     imagery: dataImagery,
18961     presets: {
18962         presets: presets,
18963         defaults: defaults,
18964         categories: categories,
18965         fields: fields
18966     }
18967 };
18968
18969 function osmEntity$$1(attrs) {
18970     // For prototypal inheritance.
18971     if (this instanceof osmEntity$$1) return;
18972
18973     // Create the appropriate subtype.
18974     if (attrs && attrs.type) {
18975         return osmEntity$$1[attrs.type].apply(this, arguments);
18976     } else if (attrs && attrs.id) {
18977         return osmEntity$$1[osmEntity$$1.id.type(attrs.id)].apply(this, arguments);
18978     }
18979
18980     // Initialize a generic Entity (used only in tests).
18981     return (new osmEntity$$1()).initialize(arguments);
18982 }
18983
18984
18985 osmEntity$$1.id = function(type) {
18986     return osmEntity$$1.id.fromOSM(type, osmEntity$$1.id.next[type]--);
18987 };
18988
18989
18990 osmEntity$$1.id.next = {
18991     node: -1, way: -1, relation: -1
18992 };
18993
18994
18995 osmEntity$$1.id.fromOSM = function(type, id) {
18996     return type[0] + id;
18997 };
18998
18999
19000 osmEntity$$1.id.toOSM = function(id) {
19001     return id.slice(1);
19002 };
19003
19004
19005 osmEntity$$1.id.type = function(id) {
19006     return { 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
19007 };
19008
19009
19010 // A function suitable for use as the second argument to d3.selection#data().
19011 osmEntity$$1.key = function(entity) {
19012     return entity.id + 'v' + (entity.v || 0);
19013 };
19014
19015
19016 osmEntity$$1.prototype = {
19017
19018     tags: {},
19019
19020
19021     initialize: function(sources) {
19022         for (var i = 0; i < sources.length; ++i) {
19023             var source = sources[i];
19024             for (var prop in source) {
19025                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
19026                     if (source[prop] === undefined) {
19027                         delete this[prop];
19028                     } else {
19029                         this[prop] = source[prop];
19030                     }
19031                 }
19032             }
19033         }
19034
19035         if (!this.id && this.type) {
19036             this.id = osmEntity$$1.id(this.type);
19037         }
19038         if (!this.hasOwnProperty('visible')) {
19039             this.visible = true;
19040         }
19041
19042         if (debug) {
19043             Object.freeze(this);
19044             Object.freeze(this.tags);
19045
19046             if (this.loc) Object.freeze(this.loc);
19047             if (this.nodes) Object.freeze(this.nodes);
19048             if (this.members) Object.freeze(this.members);
19049         }
19050
19051         return this;
19052     },
19053
19054
19055     copy: function(resolver, copies) {
19056         if (copies[this.id])
19057             return copies[this.id];
19058
19059         var copy = osmEntity$$1(this, {id: undefined, user: undefined, version: undefined});
19060         copies[this.id] = copy;
19061
19062         return copy;
19063     },
19064
19065
19066     osmId: function() {
19067         return osmEntity$$1.id.toOSM(this.id);
19068     },
19069
19070
19071     isNew: function() {
19072         return this.osmId() < 0;
19073     },
19074
19075
19076     update: function(attrs) {
19077         return osmEntity$$1(this, attrs, {v: 1 + (this.v || 0)});
19078     },
19079
19080
19081     mergeTags: function(tags) {
19082         var merged = lodash.clone(this.tags), changed = false;
19083         for (var k in tags) {
19084             var t1 = merged[k],
19085                 t2 = tags[k];
19086             if (!t1) {
19087                 changed = true;
19088                 merged[k] = t2;
19089             } else if (t1 !== t2) {
19090                 changed = true;
19091                 merged[k] = lodash.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
19092             }
19093         }
19094         return changed ? this.update({tags: merged}) : this;
19095     },
19096
19097
19098     intersects: function(extent, resolver) {
19099         return this.extent(resolver).intersects(extent);
19100     },
19101
19102
19103     isUsed: function(resolver) {
19104         return lodash.without(Object.keys(this.tags), 'area').length > 0 ||
19105             resolver.parentRelations(this).length > 0;
19106     },
19107
19108
19109     hasInterestingTags: function() {
19110         return lodash.keys(this.tags).some(osmIsInterestingTag);
19111     },
19112
19113
19114     isHighwayIntersection: function() {
19115         return false;
19116     },
19117
19118
19119     deprecatedTags: function() {
19120         var tags = lodash.toPairs(this.tags);
19121         var deprecated = {};
19122
19123         dataDeprecated.forEach(function(d) {
19124             var match = lodash.toPairs(d.old)[0];
19125             tags.forEach(function(t) {
19126                 if (t[0] === match[0] &&
19127                     (t[1] === match[1] || match[1] === '*')) {
19128                     deprecated[t[0]] = t[1];
19129                 }
19130             });
19131         });
19132
19133         return deprecated;
19134     }
19135 };
19136
19137 function geoExtent$$1(min, max) {
19138     if (!(this instanceof geoExtent$$1)) return new geoExtent$$1(min, max);
19139     if (min instanceof geoExtent$$1) {
19140         return min;
19141     } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
19142         this[0] = min[0];
19143         this[1] = min[1];
19144     } else {
19145         this[0] = min        || [ Infinity,  Infinity];
19146         this[1] = max || min || [-Infinity, -Infinity];
19147     }
19148 }
19149
19150 geoExtent$$1.prototype = new Array(2);
19151
19152 lodash.extend(geoExtent$$1.prototype, {
19153
19154     equals: function (obj) {
19155         return this[0][0] === obj[0][0] &&
19156             this[0][1] === obj[0][1] &&
19157             this[1][0] === obj[1][0] &&
19158             this[1][1] === obj[1][1];
19159     },
19160
19161
19162     extend: function(obj) {
19163         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19164         return geoExtent$$1(
19165             [Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
19166             [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
19167         );
19168     },
19169
19170
19171     _extend: function(extent) {
19172         this[0][0] = Math.min(extent[0][0], this[0][0]);
19173         this[0][1] = Math.min(extent[0][1], this[0][1]);
19174         this[1][0] = Math.max(extent[1][0], this[1][0]);
19175         this[1][1] = Math.max(extent[1][1], this[1][1]);
19176     },
19177
19178
19179     area: function() {
19180         return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
19181     },
19182
19183
19184     center: function() {
19185         return [(this[0][0] + this[1][0]) / 2,
19186                 (this[0][1] + this[1][1]) / 2];
19187     },
19188
19189
19190     rectangle: function() {
19191         return [this[0][0], this[0][1], this[1][0], this[1][1]];
19192     },
19193
19194
19195     bbox: function() {
19196         return { minX: this[0][0], minY: this[0][1], maxX: this[1][0], maxY: this[1][1] };
19197     },
19198
19199
19200     polygon: function() {
19201         return [
19202             [this[0][0], this[0][1]],
19203             [this[0][0], this[1][1]],
19204             [this[1][0], this[1][1]],
19205             [this[1][0], this[0][1]],
19206             [this[0][0], this[0][1]]
19207         ];
19208     },
19209
19210
19211     contains: function(obj) {
19212         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19213         return obj[0][0] >= this[0][0] &&
19214                obj[0][1] >= this[0][1] &&
19215                obj[1][0] <= this[1][0] &&
19216                obj[1][1] <= this[1][1];
19217     },
19218
19219
19220     intersects: function(obj) {
19221         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19222         return obj[0][0] <= this[1][0] &&
19223                obj[0][1] <= this[1][1] &&
19224                obj[1][0] >= this[0][0] &&
19225                obj[1][1] >= this[0][1];
19226     },
19227
19228
19229     intersection: function(obj) {
19230         if (!this.intersects(obj)) return new geoExtent$$1();
19231         return new geoExtent$$1(
19232             [Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
19233             [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
19234         );
19235     },
19236
19237
19238     percentContainedIn: function(obj) {
19239         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19240         var a1 = this.intersection(obj).area(),
19241             a2 = this.area();
19242
19243         if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
19244             return 0;
19245         } else {
19246             return a1 / a2;
19247         }
19248     },
19249
19250
19251     padByMeters: function(meters) {
19252         var dLat = geoMetersToLat(meters),
19253             dLon = geoMetersToLon(meters, this.center()[1]);
19254         return geoExtent$$1(
19255             [this[0][0] - dLon, this[0][1] - dLat],
19256             [this[1][0] + dLon, this[1][1] + dLat]
19257         );
19258     },
19259
19260
19261     toParam: function() {
19262         return this.rectangle().join(',');
19263     }
19264
19265 });
19266
19267 var version = "4.4.0";
19268
19269 var ascending = function(a, b) {
19270   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
19271 };
19272
19273 var bisector = function(compare) {
19274   if (compare.length === 1) compare = ascendingComparator(compare);
19275   return {
19276     left: function(a, x, lo, hi) {
19277       if (lo == null) lo = 0;
19278       if (hi == null) hi = a.length;
19279       while (lo < hi) {
19280         var mid = lo + hi >>> 1;
19281         if (compare(a[mid], x) < 0) lo = mid + 1;
19282         else hi = mid;
19283       }
19284       return lo;
19285     },
19286     right: function(a, x, lo, hi) {
19287       if (lo == null) lo = 0;
19288       if (hi == null) hi = a.length;
19289       while (lo < hi) {
19290         var mid = lo + hi >>> 1;
19291         if (compare(a[mid], x) > 0) hi = mid;
19292         else lo = mid + 1;
19293       }
19294       return lo;
19295     }
19296   };
19297 };
19298
19299 function ascendingComparator(f) {
19300   return function(d, x) {
19301     return ascending(f(d), x);
19302   };
19303 }
19304
19305 var ascendingBisect = bisector(ascending);
19306 var bisectRight = ascendingBisect.right;
19307 var bisectLeft = ascendingBisect.left;
19308
19309 var descending = function(a, b) {
19310   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
19311 };
19312
19313 var number = function(x) {
19314   return x === null ? NaN : +x;
19315 };
19316
19317 var variance = function(array, f) {
19318   var n = array.length,
19319       m = 0,
19320       a,
19321       d,
19322       s = 0,
19323       i = -1,
19324       j = 0;
19325
19326   if (f == null) {
19327     while (++i < n) {
19328       if (!isNaN(a = number(array[i]))) {
19329         d = a - m;
19330         m += d / ++j;
19331         s += d * (a - m);
19332       }
19333     }
19334   }
19335
19336   else {
19337     while (++i < n) {
19338       if (!isNaN(a = number(f(array[i], i, array)))) {
19339         d = a - m;
19340         m += d / ++j;
19341         s += d * (a - m);
19342       }
19343     }
19344   }
19345
19346   if (j > 1) return s / (j - 1);
19347 };
19348
19349 var deviation = function(array, f) {
19350   var v = variance(array, f);
19351   return v ? Math.sqrt(v) : v;
19352 };
19353
19354 var extent = function(array, f) {
19355   var i = -1,
19356       n = array.length,
19357       a,
19358       b,
19359       c;
19360
19361   if (f == null) {
19362     while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; }
19363     while (++i < n) if ((b = array[i]) != null) {
19364       if (a > b) a = b;
19365       if (c < b) c = b;
19366     }
19367   }
19368
19369   else {
19370     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = c = b; break; }
19371     while (++i < n) if ((b = f(array[i], i, array)) != null) {
19372       if (a > b) a = b;
19373       if (c < b) c = b;
19374     }
19375   }
19376
19377   return [a, c];
19378 };
19379
19380 var array = Array.prototype;
19381
19382 var slice = array.slice;
19383 var map = array.map;
19384
19385 var constant$1 = function(x) {
19386   return function() {
19387     return x;
19388   };
19389 };
19390
19391 var identity = function(x) {
19392   return x;
19393 };
19394
19395 var range = function(start, stop, step) {
19396   start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
19397
19398   var i = -1,
19399       n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
19400       range = new Array(n);
19401
19402   while (++i < n) {
19403     range[i] = start + i * step;
19404   }
19405
19406   return range;
19407 };
19408
19409 var e10 = Math.sqrt(50);
19410 var e5 = Math.sqrt(10);
19411 var e2 = Math.sqrt(2);
19412
19413 var ticks = function(start, stop, count) {
19414   var step = tickStep(start, stop, count);
19415   return range(
19416     Math.ceil(start / step) * step,
19417     Math.floor(stop / step) * step + step / 2, // inclusive
19418     step
19419   );
19420 };
19421
19422 function tickStep(start, stop, count) {
19423   var step0 = Math.abs(stop - start) / Math.max(0, count),
19424       step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
19425       error = step0 / step1;
19426   if (error >= e10) step1 *= 10;
19427   else if (error >= e5) step1 *= 5;
19428   else if (error >= e2) step1 *= 2;
19429   return stop < start ? -step1 : step1;
19430 }
19431
19432 var sturges = function(values) {
19433   return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
19434 };
19435
19436 var histogram = function() {
19437   var value = identity,
19438       domain = extent,
19439       threshold = sturges;
19440
19441   function histogram(data) {
19442     var i,
19443         n = data.length,
19444         x,
19445         values = new Array(n);
19446
19447     for (i = 0; i < n; ++i) {
19448       values[i] = value(data[i], i, data);
19449     }
19450
19451     var xz = domain(values),
19452         x0 = xz[0],
19453         x1 = xz[1],
19454         tz = threshold(values, x0, x1);
19455
19456     // Convert number of thresholds into uniform thresholds.
19457     if (!Array.isArray(tz)) tz = ticks(x0, x1, tz);
19458
19459     // Remove any thresholds outside the domain.
19460     var m = tz.length;
19461     while (tz[0] <= x0) tz.shift(), --m;
19462     while (tz[m - 1] >= x1) tz.pop(), --m;
19463
19464     var bins = new Array(m + 1),
19465         bin;
19466
19467     // Initialize bins.
19468     for (i = 0; i <= m; ++i) {
19469       bin = bins[i] = [];
19470       bin.x0 = i > 0 ? tz[i - 1] : x0;
19471       bin.x1 = i < m ? tz[i] : x1;
19472     }
19473
19474     // Assign data to bins by value, ignoring any outside the domain.
19475     for (i = 0; i < n; ++i) {
19476       x = values[i];
19477       if (x0 <= x && x <= x1) {
19478         bins[bisectRight(tz, x, 0, m)].push(data[i]);
19479       }
19480     }
19481
19482     return bins;
19483   }
19484
19485   histogram.value = function(_) {
19486     return arguments.length ? (value = typeof _ === "function" ? _ : constant$1(_), histogram) : value;
19487   };
19488
19489   histogram.domain = function(_) {
19490     return arguments.length ? (domain = typeof _ === "function" ? _ : constant$1([_[0], _[1]]), histogram) : domain;
19491   };
19492
19493   histogram.thresholds = function(_) {
19494     return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant$1(slice.call(_)) : constant$1(_), histogram) : threshold;
19495   };
19496
19497   return histogram;
19498 };
19499
19500 var threshold = function(array, p, f) {
19501   if (f == null) f = number;
19502   if (!(n = array.length)) return;
19503   if ((p = +p) <= 0 || n < 2) return +f(array[0], 0, array);
19504   if (p >= 1) return +f(array[n - 1], n - 1, array);
19505   var n,
19506       h = (n - 1) * p,
19507       i = Math.floor(h),
19508       a = +f(array[i], i, array),
19509       b = +f(array[i + 1], i + 1, array);
19510   return a + (b - a) * (h - i);
19511 };
19512
19513 var freedmanDiaconis = function(values, min, max) {
19514   values = map.call(values, number).sort(ascending);
19515   return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3)));
19516 };
19517
19518 var scott = function(values, min, max) {
19519   return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
19520 };
19521
19522 var max = function(array, f) {
19523   var i = -1,
19524       n = array.length,
19525       a,
19526       b;
19527
19528   if (f == null) {
19529     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19530     while (++i < n) if ((b = array[i]) != null && b > a) a = b;
19531   }
19532
19533   else {
19534     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19535     while (++i < n) if ((b = f(array[i], i, array)) != null && b > a) a = b;
19536   }
19537
19538   return a;
19539 };
19540
19541 var mean = function(array, f) {
19542   var s = 0,
19543       n = array.length,
19544       a,
19545       i = -1,
19546       j = n;
19547
19548   if (f == null) {
19549     while (++i < n) if (!isNaN(a = number(array[i]))) s += a; else --j;
19550   }
19551
19552   else {
19553     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) s += a; else --j;
19554   }
19555
19556   if (j) return s / j;
19557 };
19558
19559 var median = function(array, f) {
19560   var numbers = [],
19561       n = array.length,
19562       a,
19563       i = -1;
19564
19565   if (f == null) {
19566     while (++i < n) if (!isNaN(a = number(array[i]))) numbers.push(a);
19567   }
19568
19569   else {
19570     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) numbers.push(a);
19571   }
19572
19573   return threshold(numbers.sort(ascending), 0.5);
19574 };
19575
19576 var merge = function(arrays) {
19577   var n = arrays.length,
19578       m,
19579       i = -1,
19580       j = 0,
19581       merged,
19582       array;
19583
19584   while (++i < n) j += arrays[i].length;
19585   merged = new Array(j);
19586
19587   while (--n >= 0) {
19588     array = arrays[n];
19589     m = array.length;
19590     while (--m >= 0) {
19591       merged[--j] = array[m];
19592     }
19593   }
19594
19595   return merged;
19596 };
19597
19598 var min = function(array, f) {
19599   var i = -1,
19600       n = array.length,
19601       a,
19602       b;
19603
19604   if (f == null) {
19605     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19606     while (++i < n) if ((b = array[i]) != null && a > b) a = b;
19607   }
19608
19609   else {
19610     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19611     while (++i < n) if ((b = f(array[i], i, array)) != null && a > b) a = b;
19612   }
19613
19614   return a;
19615 };
19616
19617 var pairs = function(array) {
19618   var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
19619   while (i < n) pairs[i] = [p, p = array[++i]];
19620   return pairs;
19621 };
19622
19623 var permute = function(array, indexes) {
19624   var i = indexes.length, permutes = new Array(i);
19625   while (i--) permutes[i] = array[indexes[i]];
19626   return permutes;
19627 };
19628
19629 var scan = function(array, compare) {
19630   if (!(n = array.length)) return;
19631   var i = 0,
19632       n,
19633       j = 0,
19634       xi,
19635       xj = array[j];
19636
19637   if (!compare) compare = ascending;
19638
19639   while (++i < n) if (compare(xi = array[i], xj) < 0 || compare(xj, xj) !== 0) xj = xi, j = i;
19640
19641   if (compare(xj, xj) === 0) return j;
19642 };
19643
19644 var shuffle = function(array, i0, i1) {
19645   var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
19646       t,
19647       i;
19648
19649   while (m) {
19650     i = Math.random() * m-- | 0;
19651     t = array[m + i0];
19652     array[m + i0] = array[i + i0];
19653     array[i + i0] = t;
19654   }
19655
19656   return array;
19657 };
19658
19659 var sum = function(array, f) {
19660   var s = 0,
19661       n = array.length,
19662       a,
19663       i = -1;
19664
19665   if (f == null) {
19666     while (++i < n) if (a = +array[i]) s += a; // Note: zero and null are equivalent.
19667   }
19668
19669   else {
19670     while (++i < n) if (a = +f(array[i], i, array)) s += a;
19671   }
19672
19673   return s;
19674 };
19675
19676 var transpose = function(matrix) {
19677   if (!(n = matrix.length)) return [];
19678   for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
19679     for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
19680       row[j] = matrix[j][i];
19681     }
19682   }
19683   return transpose;
19684 };
19685
19686 function length(d) {
19687   return d.length;
19688 }
19689
19690 var zip = function() {
19691   return transpose(arguments);
19692 };
19693
19694 var prefix = "$";
19695
19696 function Map() {}
19697
19698 Map.prototype = map$1.prototype = {
19699   constructor: Map,
19700   has: function(key) {
19701     return (prefix + key) in this;
19702   },
19703   get: function(key) {
19704     return this[prefix + key];
19705   },
19706   set: function(key, value) {
19707     this[prefix + key] = value;
19708     return this;
19709   },
19710   remove: function(key) {
19711     var property = prefix + key;
19712     return property in this && delete this[property];
19713   },
19714   clear: function() {
19715     for (var property in this) if (property[0] === prefix) delete this[property];
19716   },
19717   keys: function() {
19718     var keys = [];
19719     for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
19720     return keys;
19721   },
19722   values: function() {
19723     var values = [];
19724     for (var property in this) if (property[0] === prefix) values.push(this[property]);
19725     return values;
19726   },
19727   entries: function() {
19728     var entries = [];
19729     for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
19730     return entries;
19731   },
19732   size: function() {
19733     var size = 0;
19734     for (var property in this) if (property[0] === prefix) ++size;
19735     return size;
19736   },
19737   empty: function() {
19738     for (var property in this) if (property[0] === prefix) return false;
19739     return true;
19740   },
19741   each: function(f) {
19742     for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
19743   }
19744 };
19745
19746 function map$1(object, f) {
19747   var map = new Map;
19748
19749   // Copy constructor.
19750   if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
19751
19752   // Index array by numeric index or specified key function.
19753   else if (Array.isArray(object)) {
19754     var i = -1,
19755         n = object.length,
19756         o;
19757
19758     if (f == null) while (++i < n) map.set(i, object[i]);
19759     else while (++i < n) map.set(f(o = object[i], i, object), o);
19760   }
19761
19762   // Convert object to map.
19763   else if (object) for (var key in object) map.set(key, object[key]);
19764
19765   return map;
19766 }
19767
19768 var nest = function() {
19769   var keys = [],
19770       sortKeys = [],
19771       sortValues,
19772       rollup,
19773       nest;
19774
19775   function apply(array, depth, createResult, setResult) {
19776     if (depth >= keys.length) return rollup != null
19777         ? rollup(array) : (sortValues != null
19778         ? array.sort(sortValues)
19779         : array);
19780
19781     var i = -1,
19782         n = array.length,
19783         key = keys[depth++],
19784         keyValue,
19785         value,
19786         valuesByKey = map$1(),
19787         values,
19788         result = createResult();
19789
19790     while (++i < n) {
19791       if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
19792         values.push(value);
19793       } else {
19794         valuesByKey.set(keyValue, [value]);
19795       }
19796     }
19797
19798     valuesByKey.each(function(values, key) {
19799       setResult(result, key, apply(values, depth, createResult, setResult));
19800     });
19801
19802     return result;
19803   }
19804
19805   function entries(map, depth) {
19806     if (++depth > keys.length) return map;
19807     var array, sortKey = sortKeys[depth - 1];
19808     if (rollup != null && depth >= keys.length) array = map.entries();
19809     else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
19810     return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
19811   }
19812
19813   return nest = {
19814     object: function(array) { return apply(array, 0, createObject, setObject); },
19815     map: function(array) { return apply(array, 0, createMap, setMap); },
19816     entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
19817     key: function(d) { keys.push(d); return nest; },
19818     sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
19819     sortValues: function(order) { sortValues = order; return nest; },
19820     rollup: function(f) { rollup = f; return nest; }
19821   };
19822 };
19823
19824 function createObject() {
19825   return {};
19826 }
19827
19828 function setObject(object, key, value) {
19829   object[key] = value;
19830 }
19831
19832 function createMap() {
19833   return map$1();
19834 }
19835
19836 function setMap(map, key, value) {
19837   map.set(key, value);
19838 }
19839
19840 function Set() {}
19841
19842 var proto = map$1.prototype;
19843
19844 Set.prototype = set.prototype = {
19845   constructor: Set,
19846   has: proto.has,
19847   add: function(value) {
19848     value += "";
19849     this[prefix + value] = value;
19850     return this;
19851   },
19852   remove: proto.remove,
19853   clear: proto.clear,
19854   values: proto.keys,
19855   size: proto.size,
19856   empty: proto.empty,
19857   each: proto.each
19858 };
19859
19860 function set(object, f) {
19861   var set = new Set;
19862
19863   // Copy constructor.
19864   if (object instanceof Set) object.each(function(value) { set.add(value); });
19865
19866   // Otherwise, assume it’s an array.
19867   else if (object) {
19868     var i = -1, n = object.length;
19869     if (f == null) while (++i < n) set.add(object[i]);
19870     else while (++i < n) set.add(f(object[i], i, object));
19871   }
19872
19873   return set;
19874 }
19875
19876 var keys = function(map) {
19877   var keys = [];
19878   for (var key in map) keys.push(key);
19879   return keys;
19880 };
19881
19882 var values = function(map) {
19883   var values = [];
19884   for (var key in map) values.push(map[key]);
19885   return values;
19886 };
19887
19888 var entries = function(map) {
19889   var entries = [];
19890   for (var key in map) entries.push({key: key, value: map[key]});
19891   return entries;
19892 };
19893
19894 var uniform = function(min, max) {
19895   min = min == null ? 0 : +min;
19896   max = max == null ? 1 : +max;
19897   if (arguments.length === 1) max = min, min = 0;
19898   else max -= min;
19899   return function() {
19900     return Math.random() * max + min;
19901   };
19902 };
19903
19904 var normal = function(mu, sigma) {
19905   var x, r;
19906   mu = mu == null ? 0 : +mu;
19907   sigma = sigma == null ? 1 : +sigma;
19908   return function() {
19909     var y;
19910
19911     // If available, use the second previously-generated uniform random.
19912     if (x != null) y = x, x = null;
19913
19914     // Otherwise, generate a new x and y.
19915     else do {
19916       x = Math.random() * 2 - 1;
19917       y = Math.random() * 2 - 1;
19918       r = x * x + y * y;
19919     } while (!r || r > 1);
19920
19921     return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
19922   };
19923 };
19924
19925 var logNormal = function() {
19926   var randomNormal = normal.apply(this, arguments);
19927   return function() {
19928     return Math.exp(randomNormal());
19929   };
19930 };
19931
19932 var irwinHall = function(n) {
19933   return function() {
19934     for (var sum = 0, i = 0; i < n; ++i) sum += Math.random();
19935     return sum;
19936   };
19937 };
19938
19939 var bates = function(n) {
19940   var randomIrwinHall = irwinHall(n);
19941   return function() {
19942     return randomIrwinHall() / n;
19943   };
19944 };
19945
19946 var exponential = function(lambda) {
19947   return function() {
19948     return -Math.log(1 - Math.random()) / lambda;
19949   };
19950 };
19951
19952 function linear(t) {
19953   return +t;
19954 }
19955
19956 function quadIn(t) {
19957   return t * t;
19958 }
19959
19960 function quadOut(t) {
19961   return t * (2 - t);
19962 }
19963
19964 function quadInOut(t) {
19965   return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
19966 }
19967
19968 function cubicIn(t) {
19969   return t * t * t;
19970 }
19971
19972 function cubicOut(t) {
19973   return --t * t * t + 1;
19974 }
19975
19976 function cubicInOut(t) {
19977   return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
19978 }
19979
19980 var exponent = 3;
19981
19982 var polyIn = (function custom(e) {
19983   e = +e;
19984
19985   function polyIn(t) {
19986     return Math.pow(t, e);
19987   }
19988
19989   polyIn.exponent = custom;
19990
19991   return polyIn;
19992 })(exponent);
19993
19994 var polyOut = (function custom(e) {
19995   e = +e;
19996
19997   function polyOut(t) {
19998     return 1 - Math.pow(1 - t, e);
19999   }
20000
20001   polyOut.exponent = custom;
20002
20003   return polyOut;
20004 })(exponent);
20005
20006 var polyInOut = (function custom(e) {
20007   e = +e;
20008
20009   function polyInOut(t) {
20010     return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
20011   }
20012
20013   polyInOut.exponent = custom;
20014
20015   return polyInOut;
20016 })(exponent);
20017
20018 var pi = Math.PI;
20019 var halfPi = pi / 2;
20020
20021 function sinIn(t) {
20022   return 1 - Math.cos(t * halfPi);
20023 }
20024
20025 function sinOut(t) {
20026   return Math.sin(t * halfPi);
20027 }
20028
20029 function sinInOut(t) {
20030   return (1 - Math.cos(pi * t)) / 2;
20031 }
20032
20033 function expIn(t) {
20034   return Math.pow(2, 10 * t - 10);
20035 }
20036
20037 function expOut(t) {
20038   return 1 - Math.pow(2, -10 * t);
20039 }
20040
20041 function expInOut(t) {
20042   return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
20043 }
20044
20045 function circleIn(t) {
20046   return 1 - Math.sqrt(1 - t * t);
20047 }
20048
20049 function circleOut(t) {
20050   return Math.sqrt(1 - --t * t);
20051 }
20052
20053 function circleInOut(t) {
20054   return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
20055 }
20056
20057 var b1 = 4 / 11;
20058 var b2 = 6 / 11;
20059 var b3 = 8 / 11;
20060 var b4 = 3 / 4;
20061 var b5 = 9 / 11;
20062 var b6 = 10 / 11;
20063 var b7 = 15 / 16;
20064 var b8 = 21 / 22;
20065 var b9 = 63 / 64;
20066 var b0 = 1 / b1 / b1;
20067
20068 function bounceIn(t) {
20069   return 1 - bounceOut(1 - t);
20070 }
20071
20072 function bounceOut(t) {
20073   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;
20074 }
20075
20076 function bounceInOut(t) {
20077   return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2;
20078 }
20079
20080 var overshoot = 1.70158;
20081
20082 var backIn = (function custom(s) {
20083   s = +s;
20084
20085   function backIn(t) {
20086     return t * t * ((s + 1) * t - s);
20087   }
20088
20089   backIn.overshoot = custom;
20090
20091   return backIn;
20092 })(overshoot);
20093
20094 var backOut = (function custom(s) {
20095   s = +s;
20096
20097   function backOut(t) {
20098     return --t * t * ((s + 1) * t + s) + 1;
20099   }
20100
20101   backOut.overshoot = custom;
20102
20103   return backOut;
20104 })(overshoot);
20105
20106 var backInOut = (function custom(s) {
20107   s = +s;
20108
20109   function backInOut(t) {
20110     return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
20111   }
20112
20113   backInOut.overshoot = custom;
20114
20115   return backInOut;
20116 })(overshoot);
20117
20118 var tau = 2 * Math.PI;
20119 var amplitude = 1;
20120 var period = 0.3;
20121
20122 var elasticIn = (function custom(a, p) {
20123   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20124
20125   function elasticIn(t) {
20126     return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
20127   }
20128
20129   elasticIn.amplitude = function(a) { return custom(a, p * tau); };
20130   elasticIn.period = function(p) { return custom(a, p); };
20131
20132   return elasticIn;
20133 })(amplitude, period);
20134
20135 var elasticOut = (function custom(a, p) {
20136   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20137
20138   function elasticOut(t) {
20139     return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
20140   }
20141
20142   elasticOut.amplitude = function(a) { return custom(a, p * tau); };
20143   elasticOut.period = function(p) { return custom(a, p); };
20144
20145   return elasticOut;
20146 })(amplitude, period);
20147
20148 var elasticInOut = (function custom(a, p) {
20149   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20150
20151   function elasticInOut(t) {
20152     return ((t = t * 2 - 1) < 0
20153         ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
20154         : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
20155   }
20156
20157   elasticInOut.amplitude = function(a) { return custom(a, p * tau); };
20158   elasticInOut.period = function(p) { return custom(a, p); };
20159
20160   return elasticInOut;
20161 })(amplitude, period);
20162
20163 var d3polygonArea = function(polygon) {
20164   var i = -1,
20165       n = polygon.length,
20166       a,
20167       b = polygon[n - 1],
20168       area = 0;
20169
20170   while (++i < n) {
20171     a = b;
20172     b = polygon[i];
20173     area += a[1] * b[0] - a[0] * b[1];
20174   }
20175
20176   return area / 2;
20177 };
20178
20179 var d3polygonCentroid = function(polygon) {
20180   var i = -1,
20181       n = polygon.length,
20182       x = 0,
20183       y = 0,
20184       a,
20185       b = polygon[n - 1],
20186       c,
20187       k = 0;
20188
20189   while (++i < n) {
20190     a = b;
20191     b = polygon[i];
20192     k += c = a[0] * b[1] - b[0] * a[1];
20193     x += (a[0] + b[0]) * c;
20194     y += (a[1] + b[1]) * c;
20195   }
20196
20197   return k *= 3, [x / k, y / k];
20198 };
20199
20200 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
20201 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
20202 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
20203 // negative if clockwise, and zero if the points are collinear.
20204 var cross = function(a, b, c) {
20205   return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
20206 };
20207
20208 function lexicographicOrder(a, b) {
20209   return a[0] - b[0] || a[1] - b[1];
20210 }
20211
20212 // Computes the upper convex hull per the monotone chain algorithm.
20213 // Assumes points.length >= 3, is sorted by x, unique in y.
20214 // Returns an array of indices into points in left-to-right order.
20215 function computeUpperHullIndexes(points) {
20216   var n = points.length,
20217       indexes = [0, 1],
20218       size = 2;
20219
20220   for (var i = 2; i < n; ++i) {
20221     while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
20222     indexes[size++] = i;
20223   }
20224
20225   return indexes.slice(0, size); // remove popped points
20226 }
20227
20228 var d3polygonHull = function(points) {
20229   if ((n = points.length) < 3) return null;
20230
20231   var i,
20232       n,
20233       sortedPoints = new Array(n),
20234       flippedPoints = new Array(n);
20235
20236   for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
20237   sortedPoints.sort(lexicographicOrder);
20238   for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
20239
20240   var upperIndexes = computeUpperHullIndexes(sortedPoints),
20241       lowerIndexes = computeUpperHullIndexes(flippedPoints);
20242
20243   // Construct the hull polygon, removing possible duplicate endpoints.
20244   var skipLeft = lowerIndexes[0] === upperIndexes[0],
20245       skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
20246       hull = [];
20247
20248   // Add upper hull in right-to-l order.
20249   // Then add lower hull in left-to-right order.
20250   for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
20251   for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
20252
20253   return hull;
20254 };
20255
20256 var contains = function(polygon, point) {
20257   var n = polygon.length,
20258       p = polygon[n - 1],
20259       x = point[0], y = point[1],
20260       x0 = p[0], y0 = p[1],
20261       x1, y1,
20262       inside = false;
20263
20264   for (var i = 0; i < n; ++i) {
20265     p = polygon[i], x1 = p[0], y1 = p[1];
20266     if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
20267     x0 = x1, y0 = y1;
20268   }
20269
20270   return inside;
20271 };
20272
20273 var length$1 = function(polygon) {
20274   var i = -1,
20275       n = polygon.length,
20276       b = polygon[n - 1],
20277       xa,
20278       ya,
20279       xb = b[0],
20280       yb = b[1],
20281       perimeter = 0;
20282
20283   while (++i < n) {
20284     xa = xb;
20285     ya = yb;
20286     b = polygon[i];
20287     xb = b[0];
20288     yb = b[1];
20289     xa -= xb;
20290     ya -= yb;
20291     perimeter += Math.sqrt(xa * xa + ya * ya);
20292   }
20293
20294   return perimeter;
20295 };
20296
20297 var pi$1 = Math.PI;
20298 var tau$1 = 2 * pi$1;
20299 var epsilon = 1e-6;
20300 var tauEpsilon = tau$1 - epsilon;
20301
20302 function Path() {
20303   this._x0 = this._y0 = // start of current subpath
20304   this._x1 = this._y1 = null; // end of current subpath
20305   this._ = "";
20306 }
20307
20308 function path() {
20309   return new Path;
20310 }
20311
20312 Path.prototype = path.prototype = {
20313   constructor: Path,
20314   moveTo: function(x, y) {
20315     this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
20316   },
20317   closePath: function() {
20318     if (this._x1 !== null) {
20319       this._x1 = this._x0, this._y1 = this._y0;
20320       this._ += "Z";
20321     }
20322   },
20323   lineTo: function(x, y) {
20324     this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
20325   },
20326   quadraticCurveTo: function(x1, y1, x, y) {
20327     this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
20328   },
20329   bezierCurveTo: function(x1, y1, x2, y2, x, y) {
20330     this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
20331   },
20332   arcTo: function(x1, y1, x2, y2, r) {
20333     x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
20334     var x0 = this._x1,
20335         y0 = this._y1,
20336         x21 = x2 - x1,
20337         y21 = y2 - y1,
20338         x01 = x0 - x1,
20339         y01 = y0 - y1,
20340         l01_2 = x01 * x01 + y01 * y01;
20341
20342     // Is the radius negative? Error.
20343     if (r < 0) throw new Error("negative radius: " + r);
20344
20345     // Is this path empty? Move to (x1,y1).
20346     if (this._x1 === null) {
20347       this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
20348     }
20349
20350     // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
20351     else if (!(l01_2 > epsilon)) {}
20352
20353     // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
20354     // Equivalently, is (x1,y1) coincident with (x2,y2)?
20355     // Or, is the radius zero? Line to (x1,y1).
20356     else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {
20357       this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
20358     }
20359
20360     // Otherwise, draw an arc!
20361     else {
20362       var x20 = x2 - x0,
20363           y20 = y2 - y0,
20364           l21_2 = x21 * x21 + y21 * y21,
20365           l20_2 = x20 * x20 + y20 * y20,
20366           l21 = Math.sqrt(l21_2),
20367           l01 = Math.sqrt(l01_2),
20368           l = r * Math.tan((pi$1 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
20369           t01 = l / l01,
20370           t21 = l / l21;
20371
20372       // If the start tangent is not coincident with (x0,y0), line to.
20373       if (Math.abs(t01 - 1) > epsilon) {
20374         this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
20375       }
20376
20377       this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
20378     }
20379   },
20380   arc: function(x, y, r, a0, a1, ccw) {
20381     x = +x, y = +y, r = +r;
20382     var dx = r * Math.cos(a0),
20383         dy = r * Math.sin(a0),
20384         x0 = x + dx,
20385         y0 = y + dy,
20386         cw = 1 ^ ccw,
20387         da = ccw ? a0 - a1 : a1 - a0;
20388
20389     // Is the radius negative? Error.
20390     if (r < 0) throw new Error("negative radius: " + r);
20391
20392     // Is this path empty? Move to (x0,y0).
20393     if (this._x1 === null) {
20394       this._ += "M" + x0 + "," + y0;
20395     }
20396
20397     // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
20398     else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
20399       this._ += "L" + x0 + "," + y0;
20400     }
20401
20402     // Is this arc empty? We’re done.
20403     if (!r) return;
20404
20405     // Is this a complete circle? Draw two arcs to complete the circle.
20406     if (da > tauEpsilon) {
20407       this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
20408     }
20409
20410     // Otherwise, draw an arc!
20411     else {
20412       if (da < 0) da = da % tau$1 + tau$1;
20413       this._ += "A" + r + "," + r + ",0," + (+(da >= pi$1)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
20414     }
20415   },
20416   rect: function(x, y, w, h) {
20417     this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z";
20418   },
20419   toString: function() {
20420     return this._;
20421   }
20422 };
20423
20424 var tree_add = function(d) {
20425   var x = +this._x.call(null, d),
20426       y = +this._y.call(null, d);
20427   return add(this.cover(x, y), x, y, d);
20428 };
20429
20430 function add(tree, x, y, d) {
20431   if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
20432
20433   var parent,
20434       node = tree._root,
20435       leaf = {data: d},
20436       x0 = tree._x0,
20437       y0 = tree._y0,
20438       x1 = tree._x1,
20439       y1 = tree._y1,
20440       xm,
20441       ym,
20442       xp,
20443       yp,
20444       right,
20445       bottom,
20446       i,
20447       j;
20448
20449   // If the tree is empty, initialize the root as a leaf.
20450   if (!node) return tree._root = leaf, tree;
20451
20452   // Find the existing leaf for the new point, or add it.
20453   while (node.length) {
20454     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20455     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20456     if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
20457   }
20458
20459   // Is the new point is exactly coincident with the existing point?
20460   xp = +tree._x.call(null, node.data);
20461   yp = +tree._y.call(null, node.data);
20462   if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
20463
20464   // Otherwise, split the leaf node until the old and new point are separated.
20465   do {
20466     parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
20467     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20468     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20469   } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
20470   return parent[j] = node, parent[i] = leaf, tree;
20471 }
20472
20473 function addAll(data) {
20474   var d, i, n = data.length,
20475       x,
20476       y,
20477       xz = new Array(n),
20478       yz = new Array(n),
20479       x0 = Infinity,
20480       y0 = Infinity,
20481       x1 = -Infinity,
20482       y1 = -Infinity;
20483
20484   // Compute the points and their extent.
20485   for (i = 0; i < n; ++i) {
20486     if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
20487     xz[i] = x;
20488     yz[i] = y;
20489     if (x < x0) x0 = x;
20490     if (x > x1) x1 = x;
20491     if (y < y0) y0 = y;
20492     if (y > y1) y1 = y;
20493   }
20494
20495   // If there were no (valid) points, inherit the existing extent.
20496   if (x1 < x0) x0 = this._x0, x1 = this._x1;
20497   if (y1 < y0) y0 = this._y0, y1 = this._y1;
20498
20499   // Expand the tree to cover the new points.
20500   this.cover(x0, y0).cover(x1, y1);
20501
20502   // Add the new points.
20503   for (i = 0; i < n; ++i) {
20504     add(this, xz[i], yz[i], data[i]);
20505   }
20506
20507   return this;
20508 }
20509
20510 var tree_cover = function(x, y) {
20511   if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
20512
20513   var x0 = this._x0,
20514       y0 = this._y0,
20515       x1 = this._x1,
20516       y1 = this._y1;
20517
20518   // If the quadtree has no extent, initialize them.
20519   // Integer extent are necessary so that if we later double the extent,
20520   // the existing quadrant boundaries don’t change due to floating point error!
20521   if (isNaN(x0)) {
20522     x1 = (x0 = Math.floor(x)) + 1;
20523     y1 = (y0 = Math.floor(y)) + 1;
20524   }
20525
20526   // Otherwise, double repeatedly to cover.
20527   else if (x0 > x || x > x1 || y0 > y || y > y1) {
20528     var z = x1 - x0,
20529         node = this._root,
20530         parent,
20531         i;
20532
20533     switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
20534       case 0: {
20535         do parent = new Array(4), parent[i] = node, node = parent;
20536         while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
20537         break;
20538       }
20539       case 1: {
20540         do parent = new Array(4), parent[i] = node, node = parent;
20541         while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
20542         break;
20543       }
20544       case 2: {
20545         do parent = new Array(4), parent[i] = node, node = parent;
20546         while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
20547         break;
20548       }
20549       case 3: {
20550         do parent = new Array(4), parent[i] = node, node = parent;
20551         while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
20552         break;
20553       }
20554     }
20555
20556     if (this._root && this._root.length) this._root = node;
20557   }
20558
20559   // If the quadtree covers the point already, just return.
20560   else return this;
20561
20562   this._x0 = x0;
20563   this._y0 = y0;
20564   this._x1 = x1;
20565   this._y1 = y1;
20566   return this;
20567 };
20568
20569 var tree_data = function() {
20570   var data = [];
20571   this.visit(function(node) {
20572     if (!node.length) do data.push(node.data); while (node = node.next)
20573   });
20574   return data;
20575 };
20576
20577 var tree_extent = function(_) {
20578   return arguments.length
20579       ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
20580       : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
20581 };
20582
20583 var Quad = function(node, x0, y0, x1, y1) {
20584   this.node = node;
20585   this.x0 = x0;
20586   this.y0 = y0;
20587   this.x1 = x1;
20588   this.y1 = y1;
20589 };
20590
20591 var tree_find = function(x, y, radius) {
20592   var data,
20593       x0 = this._x0,
20594       y0 = this._y0,
20595       x1,
20596       y1,
20597       x2,
20598       y2,
20599       x3 = this._x1,
20600       y3 = this._y1,
20601       quads = [],
20602       node = this._root,
20603       q,
20604       i;
20605
20606   if (node) quads.push(new Quad(node, x0, y0, x3, y3));
20607   if (radius == null) radius = Infinity;
20608   else {
20609     x0 = x - radius, y0 = y - radius;
20610     x3 = x + radius, y3 = y + radius;
20611     radius *= radius;
20612   }
20613
20614   while (q = quads.pop()) {
20615
20616     // Stop searching if this quadrant can’t contain a closer node.
20617     if (!(node = q.node)
20618         || (x1 = q.x0) > x3
20619         || (y1 = q.y0) > y3
20620         || (x2 = q.x1) < x0
20621         || (y2 = q.y1) < y0) continue;
20622
20623     // Bisect the current quadrant.
20624     if (node.length) {
20625       var xm = (x1 + x2) / 2,
20626           ym = (y1 + y2) / 2;
20627
20628       quads.push(
20629         new Quad(node[3], xm, ym, x2, y2),
20630         new Quad(node[2], x1, ym, xm, y2),
20631         new Quad(node[1], xm, y1, x2, ym),
20632         new Quad(node[0], x1, y1, xm, ym)
20633       );
20634
20635       // Visit the closest quadrant first.
20636       if (i = (y >= ym) << 1 | (x >= xm)) {
20637         q = quads[quads.length - 1];
20638         quads[quads.length - 1] = quads[quads.length - 1 - i];
20639         quads[quads.length - 1 - i] = q;
20640       }
20641     }
20642
20643     // Visit this point. (Visiting coincident points isn’t necessary!)
20644     else {
20645       var dx = x - +this._x.call(null, node.data),
20646           dy = y - +this._y.call(null, node.data),
20647           d2 = dx * dx + dy * dy;
20648       if (d2 < radius) {
20649         var d = Math.sqrt(radius = d2);
20650         x0 = x - d, y0 = y - d;
20651         x3 = x + d, y3 = y + d;
20652         data = node.data;
20653       }
20654     }
20655   }
20656
20657   return data;
20658 };
20659
20660 var tree_remove = function(d) {
20661   if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
20662
20663   var parent,
20664       node = this._root,
20665       retainer,
20666       previous,
20667       next,
20668       x0 = this._x0,
20669       y0 = this._y0,
20670       x1 = this._x1,
20671       y1 = this._y1,
20672       x,
20673       y,
20674       xm,
20675       ym,
20676       right,
20677       bottom,
20678       i,
20679       j;
20680
20681   // If the tree is empty, initialize the root as a leaf.
20682   if (!node) return this;
20683
20684   // Find the leaf node for the point.
20685   // While descending, also retain the deepest parent with a non-removed sibling.
20686   if (node.length) while (true) {
20687     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20688     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20689     if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
20690     if (!node.length) break;
20691     if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
20692   }
20693
20694   // Find the point to remove.
20695   while (node.data !== d) if (!(previous = node, node = node.next)) return this;
20696   if (next = node.next) delete node.next;
20697
20698   // If there are multiple coincident points, remove just the point.
20699   if (previous) return (next ? previous.next = next : delete previous.next), this;
20700
20701   // If this is the root point, remove it.
20702   if (!parent) return this._root = next, this;
20703
20704   // Remove this leaf.
20705   next ? parent[i] = next : delete parent[i];
20706
20707   // If the parent now contains exactly one leaf, collapse superfluous parents.
20708   if ((node = parent[0] || parent[1] || parent[2] || parent[3])
20709       && node === (parent[3] || parent[2] || parent[1] || parent[0])
20710       && !node.length) {
20711     if (retainer) retainer[j] = node;
20712     else this._root = node;
20713   }
20714
20715   return this;
20716 };
20717
20718 function removeAll(data) {
20719   for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
20720   return this;
20721 }
20722
20723 var tree_root = function() {
20724   return this._root;
20725 };
20726
20727 var tree_size = function() {
20728   var size = 0;
20729   this.visit(function(node) {
20730     if (!node.length) do ++size; while (node = node.next)
20731   });
20732   return size;
20733 };
20734
20735 var tree_visit = function(callback) {
20736   var quads = [], q, node = this._root, child, x0, y0, x1, y1;
20737   if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
20738   while (q = quads.pop()) {
20739     if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
20740       var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
20741       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
20742       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
20743       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
20744       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
20745     }
20746   }
20747   return this;
20748 };
20749
20750 var tree_visitAfter = function(callback) {
20751   var quads = [], next = [], q;
20752   if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
20753   while (q = quads.pop()) {
20754     var node = q.node;
20755     if (node.length) {
20756       var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
20757       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
20758       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
20759       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
20760       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
20761     }
20762     next.push(q);
20763   }
20764   while (q = next.pop()) {
20765     callback(q.node, q.x0, q.y0, q.x1, q.y1);
20766   }
20767   return this;
20768 };
20769
20770 function defaultX(d) {
20771   return d[0];
20772 }
20773
20774 var tree_x = function(_) {
20775   return arguments.length ? (this._x = _, this) : this._x;
20776 };
20777
20778 function defaultY(d) {
20779   return d[1];
20780 }
20781
20782 var tree_y = function(_) {
20783   return arguments.length ? (this._y = _, this) : this._y;
20784 };
20785
20786 function quadtree(nodes, x, y) {
20787   var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
20788   return nodes == null ? tree : tree.addAll(nodes);
20789 }
20790
20791 function Quadtree(x, y, x0, y0, x1, y1) {
20792   this._x = x;
20793   this._y = y;
20794   this._x0 = x0;
20795   this._y0 = y0;
20796   this._x1 = x1;
20797   this._y1 = y1;
20798   this._root = undefined;
20799 }
20800
20801 function leaf_copy(leaf) {
20802   var copy = {data: leaf.data}, next = copy;
20803   while (leaf = leaf.next) next = next.next = {data: leaf.data};
20804   return copy;
20805 }
20806
20807 var treeProto = quadtree.prototype = Quadtree.prototype;
20808
20809 treeProto.copy = function() {
20810   var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
20811       node = this._root,
20812       nodes,
20813       child;
20814
20815   if (!node) return copy;
20816
20817   if (!node.length) return copy._root = leaf_copy(node), copy;
20818
20819   nodes = [{source: node, target: copy._root = new Array(4)}];
20820   while (node = nodes.pop()) {
20821     for (var i = 0; i < 4; ++i) {
20822       if (child = node.source[i]) {
20823         if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
20824         else node.target[i] = leaf_copy(child);
20825       }
20826     }
20827   }
20828
20829   return copy;
20830 };
20831
20832 treeProto.add = tree_add;
20833 treeProto.addAll = addAll;
20834 treeProto.cover = tree_cover;
20835 treeProto.data = tree_data;
20836 treeProto.extent = tree_extent;
20837 treeProto.find = tree_find;
20838 treeProto.remove = tree_remove;
20839 treeProto.removeAll = removeAll;
20840 treeProto.root = tree_root;
20841 treeProto.size = tree_size;
20842 treeProto.visit = tree_visit;
20843 treeProto.visitAfter = tree_visitAfter;
20844 treeProto.x = tree_x;
20845 treeProto.y = tree_y;
20846
20847 var slice$1 = [].slice;
20848
20849 var noabort = {};
20850
20851 function Queue(size) {
20852   if (!(size >= 1)) throw new Error;
20853   this._size = size;
20854   this._call =
20855   this._error = null;
20856   this._tasks = [];
20857   this._data = [];
20858   this._waiting =
20859   this._active =
20860   this._ended =
20861   this._start = 0; // inside a synchronous task callback?
20862 }
20863
20864 Queue.prototype = queue.prototype = {
20865   constructor: Queue,
20866   defer: function(callback) {
20867     if (typeof callback !== "function" || this._call) throw new Error;
20868     if (this._error != null) return this;
20869     var t = slice$1.call(arguments, 1);
20870     t.push(callback);
20871     ++this._waiting, this._tasks.push(t);
20872     poke(this);
20873     return this;
20874   },
20875   abort: function() {
20876     if (this._error == null) abort(this, new Error("abort"));
20877     return this;
20878   },
20879   await: function(callback) {
20880     if (typeof callback !== "function" || this._call) throw new Error;
20881     this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
20882     maybeNotify(this);
20883     return this;
20884   },
20885   awaitAll: function(callback) {
20886     if (typeof callback !== "function" || this._call) throw new Error;
20887     this._call = callback;
20888     maybeNotify(this);
20889     return this;
20890   }
20891 };
20892
20893 function poke(q) {
20894   if (!q._start) {
20895     try { start(q); } // let the current task complete
20896     catch (e) {
20897       if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
20898       else if (!q._data) throw e; // await callback errored synchronously
20899     }
20900   }
20901 }
20902
20903 function start(q) {
20904   while (q._start = q._waiting && q._active < q._size) {
20905     var i = q._ended + q._active,
20906         t = q._tasks[i],
20907         j = t.length - 1,
20908         c = t[j];
20909     t[j] = end(q, i);
20910     --q._waiting, ++q._active;
20911     t = c.apply(null, t);
20912     if (!q._tasks[i]) continue; // task finished synchronously
20913     q._tasks[i] = t || noabort;
20914   }
20915 }
20916
20917 function end(q, i) {
20918   return function(e, r) {
20919     if (!q._tasks[i]) return; // ignore multiple callbacks
20920     --q._active, ++q._ended;
20921     q._tasks[i] = null;
20922     if (q._error != null) return; // ignore secondary errors
20923     if (e != null) {
20924       abort(q, e);
20925     } else {
20926       q._data[i] = r;
20927       if (q._waiting) poke(q);
20928       else maybeNotify(q);
20929     }
20930   };
20931 }
20932
20933 function abort(q, e) {
20934   var i = q._tasks.length, t;
20935   q._error = e; // ignore active callbacks
20936   q._data = undefined; // allow gc
20937   q._waiting = NaN; // prevent starting
20938
20939   while (--i >= 0) {
20940     if (t = q._tasks[i]) {
20941       q._tasks[i] = null;
20942       if (t.abort) {
20943         try { t.abort(); }
20944         catch (e) { /* ignore */ }
20945       }
20946     }
20947   }
20948
20949   q._active = NaN; // allow notification
20950   maybeNotify(q);
20951 }
20952
20953 function maybeNotify(q) {
20954   if (!q._active && q._call) {
20955     var d = q._data;
20956     q._data = undefined; // allow gc
20957     q._call(q._error, d);
20958   }
20959 }
20960
20961 function queue(concurrency) {
20962   return new Queue(arguments.length ? +concurrency : Infinity);
20963 }
20964
20965 var constant$2 = function(x) {
20966   return function constant() {
20967     return x;
20968   };
20969 };
20970
20971 var epsilon$1 = 1e-12;
20972 var pi$2 = Math.PI;
20973 var halfPi$1 = pi$2 / 2;
20974 var tau$2 = 2 * pi$2;
20975
20976 function arcInnerRadius(d) {
20977   return d.innerRadius;
20978 }
20979
20980 function arcOuterRadius(d) {
20981   return d.outerRadius;
20982 }
20983
20984 function arcStartAngle(d) {
20985   return d.startAngle;
20986 }
20987
20988 function arcEndAngle(d) {
20989   return d.endAngle;
20990 }
20991
20992 function arcPadAngle(d) {
20993   return d && d.padAngle; // Note: optional!
20994 }
20995
20996 function asin(x) {
20997   return x >= 1 ? halfPi$1 : x <= -1 ? -halfPi$1 : Math.asin(x);
20998 }
20999
21000 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
21001   var x10 = x1 - x0, y10 = y1 - y0,
21002       x32 = x3 - x2, y32 = y3 - y2,
21003       t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
21004   return [x0 + t * x10, y0 + t * y10];
21005 }
21006
21007 // Compute perpendicular offset line of length rc.
21008 // http://mathworld.wolfram.com/Circle-LineIntersection.html
21009 function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
21010   var x01 = x0 - x1,
21011       y01 = y0 - y1,
21012       lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01),
21013       ox = lo * y01,
21014       oy = -lo * x01,
21015       x11 = x0 + ox,
21016       y11 = y0 + oy,
21017       x10 = x1 + ox,
21018       y10 = y1 + oy,
21019       x00 = (x11 + x10) / 2,
21020       y00 = (y11 + y10) / 2,
21021       dx = x10 - x11,
21022       dy = y10 - y11,
21023       d2 = dx * dx + dy * dy,
21024       r = r1 - rc,
21025       D = x11 * y10 - x10 * y11,
21026       d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)),
21027       cx0 = (D * dy - dx * d) / d2,
21028       cy0 = (-D * dx - dy * d) / d2,
21029       cx1 = (D * dy + dx * d) / d2,
21030       cy1 = (-D * dx + dy * d) / d2,
21031       dx0 = cx0 - x00,
21032       dy0 = cy0 - y00,
21033       dx1 = cx1 - x00,
21034       dy1 = cy1 - y00;
21035
21036   // Pick the closer of the two intersection points.
21037   // TODO Is there a faster way to determine which intersection to use?
21038   if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
21039
21040   return {
21041     cx: cx0,
21042     cy: cy0,
21043     x01: -ox,
21044     y01: -oy,
21045     x11: cx0 * (r1 / r - 1),
21046     y11: cy0 * (r1 / r - 1)
21047   };
21048 }
21049
21050 var arc = function() {
21051   var innerRadius = arcInnerRadius,
21052       outerRadius = arcOuterRadius,
21053       cornerRadius = constant$2(0),
21054       padRadius = null,
21055       startAngle = arcStartAngle,
21056       endAngle = arcEndAngle,
21057       padAngle = arcPadAngle,
21058       context = null;
21059
21060   function arc() {
21061     var buffer,
21062         r,
21063         r0 = +innerRadius.apply(this, arguments),
21064         r1 = +outerRadius.apply(this, arguments),
21065         a0 = startAngle.apply(this, arguments) - halfPi$1,
21066         a1 = endAngle.apply(this, arguments) - halfPi$1,
21067         da = Math.abs(a1 - a0),
21068         cw = a1 > a0;
21069
21070     if (!context) context = buffer = path();
21071
21072     // Ensure that the outer radius is always larger than the inner radius.
21073     if (r1 < r0) r = r1, r1 = r0, r0 = r;
21074
21075     // Is it a point?
21076     if (!(r1 > epsilon$1)) context.moveTo(0, 0);
21077
21078     // Or is it a circle or annulus?
21079     else if (da > tau$2 - epsilon$1) {
21080       context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0));
21081       context.arc(0, 0, r1, a0, a1, !cw);
21082       if (r0 > epsilon$1) {
21083         context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1));
21084         context.arc(0, 0, r0, a1, a0, cw);
21085       }
21086     }
21087
21088     // Or is it a circular or annular sector?
21089     else {
21090       var a01 = a0,
21091           a11 = a1,
21092           a00 = a0,
21093           a10 = a1,
21094           da0 = da,
21095           da1 = da,
21096           ap = padAngle.apply(this, arguments) / 2,
21097           rp = (ap > epsilon$1) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)),
21098           rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
21099           rc0 = rc,
21100           rc1 = rc,
21101           t0,
21102           t1;
21103
21104       // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
21105       if (rp > epsilon$1) {
21106         var p0 = asin(rp / r0 * Math.sin(ap)),
21107             p1 = asin(rp / r1 * Math.sin(ap));
21108         if ((da0 -= p0 * 2) > epsilon$1) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
21109         else da0 = 0, a00 = a10 = (a0 + a1) / 2;
21110         if ((da1 -= p1 * 2) > epsilon$1) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
21111         else da1 = 0, a01 = a11 = (a0 + a1) / 2;
21112       }
21113
21114       var x01 = r1 * Math.cos(a01),
21115           y01 = r1 * Math.sin(a01),
21116           x10 = r0 * Math.cos(a10),
21117           y10 = r0 * Math.sin(a10);
21118
21119       // Apply rounded corners?
21120       if (rc > epsilon$1) {
21121         var x11 = r1 * Math.cos(a11),
21122             y11 = r1 * Math.sin(a11),
21123             x00 = r0 * Math.cos(a00),
21124             y00 = r0 * Math.sin(a00);
21125
21126         // Restrict the corner radius according to the sector angle.
21127         if (da < pi$2) {
21128           var oc = da0 > epsilon$1 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
21129               ax = x01 - oc[0],
21130               ay = y01 - oc[1],
21131               bx = x11 - oc[0],
21132               by = y11 - oc[1],
21133               kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2),
21134               lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
21135           rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
21136           rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
21137         }
21138       }
21139
21140       // Is the sector collapsed to a line?
21141       if (!(da1 > epsilon$1)) context.moveTo(x01, y01);
21142
21143       // Does the sector’s outer ring have rounded corners?
21144       else if (rc1 > epsilon$1) {
21145         t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
21146         t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
21147
21148         context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
21149
21150         // Have the corners merged?
21151         if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
21152
21153         // Otherwise, draw the two corners and the ring.
21154         else {
21155           context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
21156           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);
21157           context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
21158         }
21159       }
21160
21161       // Or is the outer ring just a circular arc?
21162       else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
21163
21164       // Is there no inner ring, and it’s a circular sector?
21165       // Or perhaps it’s an annular sector collapsed due to padding?
21166       if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10);
21167
21168       // Does the sector’s inner ring (or point) have rounded corners?
21169       else if (rc0 > epsilon$1) {
21170         t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
21171         t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
21172
21173         context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
21174
21175         // Have the corners merged?
21176         if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
21177
21178         // Otherwise, draw the two corners and the ring.
21179         else {
21180           context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
21181           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);
21182           context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
21183         }
21184       }
21185
21186       // Or is the inner ring just a circular arc?
21187       else context.arc(0, 0, r0, a10, a00, cw);
21188     }
21189
21190     context.closePath();
21191
21192     if (buffer) return context = null, buffer + "" || null;
21193   }
21194
21195   arc.centroid = function() {
21196     var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
21197         a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$2 / 2;
21198     return [Math.cos(a) * r, Math.sin(a) * r];
21199   };
21200
21201   arc.innerRadius = function(_) {
21202     return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : innerRadius;
21203   };
21204
21205   arc.outerRadius = function(_) {
21206     return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : outerRadius;
21207   };
21208
21209   arc.cornerRadius = function(_) {
21210     return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : cornerRadius;
21211   };
21212
21213   arc.padRadius = function(_) {
21214     return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), arc) : padRadius;
21215   };
21216
21217   arc.startAngle = function(_) {
21218     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : startAngle;
21219   };
21220
21221   arc.endAngle = function(_) {
21222     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : endAngle;
21223   };
21224
21225   arc.padAngle = function(_) {
21226     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : padAngle;
21227   };
21228
21229   arc.context = function(_) {
21230     return arguments.length ? ((context = _ == null ? null : _), arc) : context;
21231   };
21232
21233   return arc;
21234 };
21235
21236 function Linear(context) {
21237   this._context = context;
21238 }
21239
21240 Linear.prototype = {
21241   areaStart: function() {
21242     this._line = 0;
21243   },
21244   areaEnd: function() {
21245     this._line = NaN;
21246   },
21247   lineStart: function() {
21248     this._point = 0;
21249   },
21250   lineEnd: function() {
21251     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21252     this._line = 1 - this._line;
21253   },
21254   point: function(x, y) {
21255     x = +x, y = +y;
21256     switch (this._point) {
21257       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21258       case 1: this._point = 2; // proceed
21259       default: this._context.lineTo(x, y); break;
21260     }
21261   }
21262 };
21263
21264 var curveLinear = function(context) {
21265   return new Linear(context);
21266 };
21267
21268 function x(p) {
21269   return p[0];
21270 }
21271
21272 function y(p) {
21273   return p[1];
21274 }
21275
21276 var line = function() {
21277   var x$$1 = x,
21278       y$$1 = y,
21279       defined = constant$2(true),
21280       context = null,
21281       curve = curveLinear,
21282       output = null;
21283
21284   function line(data) {
21285     var i,
21286         n = data.length,
21287         d,
21288         defined0 = false,
21289         buffer;
21290
21291     if (context == null) output = curve(buffer = path());
21292
21293     for (i = 0; i <= n; ++i) {
21294       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
21295         if (defined0 = !defined0) output.lineStart();
21296         else output.lineEnd();
21297       }
21298       if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data));
21299     }
21300
21301     if (buffer) return output = null, buffer + "" || null;
21302   }
21303
21304   line.x = function(_) {
21305     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : x$$1;
21306   };
21307
21308   line.y = function(_) {
21309     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : y$$1;
21310   };
21311
21312   line.defined = function(_) {
21313     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), line) : defined;
21314   };
21315
21316   line.curve = function(_) {
21317     return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
21318   };
21319
21320   line.context = function(_) {
21321     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
21322   };
21323
21324   return line;
21325 };
21326
21327 var area = function() {
21328   var x0 = x,
21329       x1 = null,
21330       y0 = constant$2(0),
21331       y1 = y,
21332       defined = constant$2(true),
21333       context = null,
21334       curve = curveLinear,
21335       output = null;
21336
21337   function area(data) {
21338     var i,
21339         j,
21340         k,
21341         n = data.length,
21342         d,
21343         defined0 = false,
21344         buffer,
21345         x0z = new Array(n),
21346         y0z = new Array(n);
21347
21348     if (context == null) output = curve(buffer = path());
21349
21350     for (i = 0; i <= n; ++i) {
21351       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
21352         if (defined0 = !defined0) {
21353           j = i;
21354           output.areaStart();
21355           output.lineStart();
21356         } else {
21357           output.lineEnd();
21358           output.lineStart();
21359           for (k = i - 1; k >= j; --k) {
21360             output.point(x0z[k], y0z[k]);
21361           }
21362           output.lineEnd();
21363           output.areaEnd();
21364         }
21365       }
21366       if (defined0) {
21367         x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
21368         output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
21369       }
21370     }
21371
21372     if (buffer) return output = null, buffer + "" || null;
21373   }
21374
21375   function arealine() {
21376     return line().defined(defined).curve(curve).context(context);
21377   }
21378
21379   area.x = function(_) {
21380     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), x1 = null, area) : x0;
21381   };
21382
21383   area.x0 = function(_) {
21384     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), area) : x0;
21385   };
21386
21387   area.x1 = function(_) {
21388     return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : x1;
21389   };
21390
21391   area.y = function(_) {
21392     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), y1 = null, area) : y0;
21393   };
21394
21395   area.y0 = function(_) {
21396     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), area) : y0;
21397   };
21398
21399   area.y1 = function(_) {
21400     return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : y1;
21401   };
21402
21403   area.lineX0 =
21404   area.lineY0 = function() {
21405     return arealine().x(x0).y(y0);
21406   };
21407
21408   area.lineY1 = function() {
21409     return arealine().x(x0).y(y1);
21410   };
21411
21412   area.lineX1 = function() {
21413     return arealine().x(x1).y(y0);
21414   };
21415
21416   area.defined = function(_) {
21417     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), area) : defined;
21418   };
21419
21420   area.curve = function(_) {
21421     return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
21422   };
21423
21424   area.context = function(_) {
21425     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
21426   };
21427
21428   return area;
21429 };
21430
21431 var descending$1 = function(a, b) {
21432   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
21433 };
21434
21435 var identity$1 = function(d) {
21436   return d;
21437 };
21438
21439 var pie = function() {
21440   var value = identity$1,
21441       sortValues = descending$1,
21442       sort = null,
21443       startAngle = constant$2(0),
21444       endAngle = constant$2(tau$2),
21445       padAngle = constant$2(0);
21446
21447   function pie(data) {
21448     var i,
21449         n = data.length,
21450         j,
21451         k,
21452         sum = 0,
21453         index = new Array(n),
21454         arcs = new Array(n),
21455         a0 = +startAngle.apply(this, arguments),
21456         da = Math.min(tau$2, Math.max(-tau$2, endAngle.apply(this, arguments) - a0)),
21457         a1,
21458         p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
21459         pa = p * (da < 0 ? -1 : 1),
21460         v;
21461
21462     for (i = 0; i < n; ++i) {
21463       if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
21464         sum += v;
21465       }
21466     }
21467
21468     // Optionally sort the arcs by previously-computed values or by data.
21469     if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
21470     else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });
21471
21472     // Compute the arcs! They are stored in the original data's order.
21473     for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
21474       j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
21475         data: data[j],
21476         index: i,
21477         value: v,
21478         startAngle: a0,
21479         endAngle: a1,
21480         padAngle: p
21481       };
21482     }
21483
21484     return arcs;
21485   }
21486
21487   pie.value = function(_) {
21488     return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), pie) : value;
21489   };
21490
21491   pie.sortValues = function(_) {
21492     return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
21493   };
21494
21495   pie.sort = function(_) {
21496     return arguments.length ? (sort = _, sortValues = null, pie) : sort;
21497   };
21498
21499   pie.startAngle = function(_) {
21500     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : startAngle;
21501   };
21502
21503   pie.endAngle = function(_) {
21504     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : endAngle;
21505   };
21506
21507   pie.padAngle = function(_) {
21508     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : padAngle;
21509   };
21510
21511   return pie;
21512 };
21513
21514 var curveRadialLinear = curveRadial(curveLinear);
21515
21516 function Radial(curve) {
21517   this._curve = curve;
21518 }
21519
21520 Radial.prototype = {
21521   areaStart: function() {
21522     this._curve.areaStart();
21523   },
21524   areaEnd: function() {
21525     this._curve.areaEnd();
21526   },
21527   lineStart: function() {
21528     this._curve.lineStart();
21529   },
21530   lineEnd: function() {
21531     this._curve.lineEnd();
21532   },
21533   point: function(a, r) {
21534     this._curve.point(r * Math.sin(a), r * -Math.cos(a));
21535   }
21536 };
21537
21538 function curveRadial(curve) {
21539
21540   function radial(context) {
21541     return new Radial(curve(context));
21542   }
21543
21544   radial._curve = curve;
21545
21546   return radial;
21547 }
21548
21549 function radialLine(l) {
21550   var c = l.curve;
21551
21552   l.angle = l.x, delete l.x;
21553   l.radius = l.y, delete l.y;
21554
21555   l.curve = function(_) {
21556     return arguments.length ? c(curveRadial(_)) : c()._curve;
21557   };
21558
21559   return l;
21560 }
21561
21562 var radialLine$1 = function() {
21563   return radialLine(line().curve(curveRadialLinear));
21564 };
21565
21566 var radialArea = function() {
21567   var a = area().curve(curveRadialLinear),
21568       c = a.curve,
21569       x0 = a.lineX0,
21570       x1 = a.lineX1,
21571       y0 = a.lineY0,
21572       y1 = a.lineY1;
21573
21574   a.angle = a.x, delete a.x;
21575   a.startAngle = a.x0, delete a.x0;
21576   a.endAngle = a.x1, delete a.x1;
21577   a.radius = a.y, delete a.y;
21578   a.innerRadius = a.y0, delete a.y0;
21579   a.outerRadius = a.y1, delete a.y1;
21580   a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0;
21581   a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1;
21582   a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0;
21583   a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1;
21584
21585   a.curve = function(_) {
21586     return arguments.length ? c(curveRadial(_)) : c()._curve;
21587   };
21588
21589   return a;
21590 };
21591
21592 var circle = {
21593   draw: function(context, size) {
21594     var r = Math.sqrt(size / pi$2);
21595     context.moveTo(r, 0);
21596     context.arc(0, 0, r, 0, tau$2);
21597   }
21598 };
21599
21600 var cross$1 = {
21601   draw: function(context, size) {
21602     var r = Math.sqrt(size / 5) / 2;
21603     context.moveTo(-3 * r, -r);
21604     context.lineTo(-r, -r);
21605     context.lineTo(-r, -3 * r);
21606     context.lineTo(r, -3 * r);
21607     context.lineTo(r, -r);
21608     context.lineTo(3 * r, -r);
21609     context.lineTo(3 * r, r);
21610     context.lineTo(r, r);
21611     context.lineTo(r, 3 * r);
21612     context.lineTo(-r, 3 * r);
21613     context.lineTo(-r, r);
21614     context.lineTo(-3 * r, r);
21615     context.closePath();
21616   }
21617 };
21618
21619 var tan30 = Math.sqrt(1 / 3);
21620 var tan30_2 = tan30 * 2;
21621
21622 var diamond = {
21623   draw: function(context, size) {
21624     var y = Math.sqrt(size / tan30_2),
21625         x = y * tan30;
21626     context.moveTo(0, -y);
21627     context.lineTo(x, 0);
21628     context.lineTo(0, y);
21629     context.lineTo(-x, 0);
21630     context.closePath();
21631   }
21632 };
21633
21634 var ka = 0.89081309152928522810;
21635 var kr = Math.sin(pi$2 / 10) / Math.sin(7 * pi$2 / 10);
21636 var kx = Math.sin(tau$2 / 10) * kr;
21637 var ky = -Math.cos(tau$2 / 10) * kr;
21638
21639 var star = {
21640   draw: function(context, size) {
21641     var r = Math.sqrt(size * ka),
21642         x = kx * r,
21643         y = ky * r;
21644     context.moveTo(0, -r);
21645     context.lineTo(x, y);
21646     for (var i = 1; i < 5; ++i) {
21647       var a = tau$2 * i / 5,
21648           c = Math.cos(a),
21649           s = Math.sin(a);
21650       context.lineTo(s * r, -c * r);
21651       context.lineTo(c * x - s * y, s * x + c * y);
21652     }
21653     context.closePath();
21654   }
21655 };
21656
21657 var square = {
21658   draw: function(context, size) {
21659     var w = Math.sqrt(size),
21660         x = -w / 2;
21661     context.rect(x, x, w, w);
21662   }
21663 };
21664
21665 var sqrt3 = Math.sqrt(3);
21666
21667 var triangle = {
21668   draw: function(context, size) {
21669     var y = -Math.sqrt(size / (sqrt3 * 3));
21670     context.moveTo(0, y * 2);
21671     context.lineTo(-sqrt3 * y, -y);
21672     context.lineTo(sqrt3 * y, -y);
21673     context.closePath();
21674   }
21675 };
21676
21677 var c = -0.5;
21678 var s = Math.sqrt(3) / 2;
21679 var k = 1 / Math.sqrt(12);
21680 var a = (k / 2 + 1) * 3;
21681
21682 var wye = {
21683   draw: function(context, size) {
21684     var r = Math.sqrt(size / a),
21685         x0 = r / 2,
21686         y0 = r * k,
21687         x1 = x0,
21688         y1 = r * k + r,
21689         x2 = -x1,
21690         y2 = y1;
21691     context.moveTo(x0, y0);
21692     context.lineTo(x1, y1);
21693     context.lineTo(x2, y2);
21694     context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
21695     context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
21696     context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
21697     context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
21698     context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
21699     context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
21700     context.closePath();
21701   }
21702 };
21703
21704 var symbols = [
21705   circle,
21706   cross$1,
21707   diamond,
21708   square,
21709   star,
21710   triangle,
21711   wye
21712 ];
21713
21714 var symbol = function() {
21715   var type = constant$2(circle),
21716       size = constant$2(64),
21717       context = null;
21718
21719   function symbol() {
21720     var buffer;
21721     if (!context) context = buffer = path();
21722     type.apply(this, arguments).draw(context, +size.apply(this, arguments));
21723     if (buffer) return context = null, buffer + "" || null;
21724   }
21725
21726   symbol.type = function(_) {
21727     return arguments.length ? (type = typeof _ === "function" ? _ : constant$2(_), symbol) : type;
21728   };
21729
21730   symbol.size = function(_) {
21731     return arguments.length ? (size = typeof _ === "function" ? _ : constant$2(+_), symbol) : size;
21732   };
21733
21734   symbol.context = function(_) {
21735     return arguments.length ? (context = _ == null ? null : _, symbol) : context;
21736   };
21737
21738   return symbol;
21739 };
21740
21741 var noop = function() {};
21742
21743 function point(that, x, y) {
21744   that._context.bezierCurveTo(
21745     (2 * that._x0 + that._x1) / 3,
21746     (2 * that._y0 + that._y1) / 3,
21747     (that._x0 + 2 * that._x1) / 3,
21748     (that._y0 + 2 * that._y1) / 3,
21749     (that._x0 + 4 * that._x1 + x) / 6,
21750     (that._y0 + 4 * that._y1 + y) / 6
21751   );
21752 }
21753
21754 function Basis(context) {
21755   this._context = context;
21756 }
21757
21758 Basis.prototype = {
21759   areaStart: function() {
21760     this._line = 0;
21761   },
21762   areaEnd: function() {
21763     this._line = NaN;
21764   },
21765   lineStart: function() {
21766     this._x0 = this._x1 =
21767     this._y0 = this._y1 = NaN;
21768     this._point = 0;
21769   },
21770   lineEnd: function() {
21771     switch (this._point) {
21772       case 3: point(this, this._x1, this._y1); // proceed
21773       case 2: this._context.lineTo(this._x1, this._y1); break;
21774     }
21775     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21776     this._line = 1 - this._line;
21777   },
21778   point: function(x, y) {
21779     x = +x, y = +y;
21780     switch (this._point) {
21781       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21782       case 1: this._point = 2; break;
21783       case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
21784       default: point(this, x, y); break;
21785     }
21786     this._x0 = this._x1, this._x1 = x;
21787     this._y0 = this._y1, this._y1 = y;
21788   }
21789 };
21790
21791 var basis = function(context) {
21792   return new Basis(context);
21793 };
21794
21795 function BasisClosed(context) {
21796   this._context = context;
21797 }
21798
21799 BasisClosed.prototype = {
21800   areaStart: noop,
21801   areaEnd: noop,
21802   lineStart: function() {
21803     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
21804     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
21805     this._point = 0;
21806   },
21807   lineEnd: function() {
21808     switch (this._point) {
21809       case 1: {
21810         this._context.moveTo(this._x2, this._y2);
21811         this._context.closePath();
21812         break;
21813       }
21814       case 2: {
21815         this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
21816         this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
21817         this._context.closePath();
21818         break;
21819       }
21820       case 3: {
21821         this.point(this._x2, this._y2);
21822         this.point(this._x3, this._y3);
21823         this.point(this._x4, this._y4);
21824         break;
21825       }
21826     }
21827   },
21828   point: function(x, y) {
21829     x = +x, y = +y;
21830     switch (this._point) {
21831       case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
21832       case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
21833       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;
21834       default: point(this, x, y); break;
21835     }
21836     this._x0 = this._x1, this._x1 = x;
21837     this._y0 = this._y1, this._y1 = y;
21838   }
21839 };
21840
21841 var basisClosed = function(context) {
21842   return new BasisClosed(context);
21843 };
21844
21845 function BasisOpen(context) {
21846   this._context = context;
21847 }
21848
21849 BasisOpen.prototype = {
21850   areaStart: function() {
21851     this._line = 0;
21852   },
21853   areaEnd: function() {
21854     this._line = NaN;
21855   },
21856   lineStart: function() {
21857     this._x0 = this._x1 =
21858     this._y0 = this._y1 = NaN;
21859     this._point = 0;
21860   },
21861   lineEnd: function() {
21862     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
21863     this._line = 1 - this._line;
21864   },
21865   point: function(x, y) {
21866     x = +x, y = +y;
21867     switch (this._point) {
21868       case 0: this._point = 1; break;
21869       case 1: this._point = 2; break;
21870       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;
21871       case 3: this._point = 4; // proceed
21872       default: point(this, x, y); break;
21873     }
21874     this._x0 = this._x1, this._x1 = x;
21875     this._y0 = this._y1, this._y1 = y;
21876   }
21877 };
21878
21879 var basisOpen = function(context) {
21880   return new BasisOpen(context);
21881 };
21882
21883 function Bundle(context, beta) {
21884   this._basis = new Basis(context);
21885   this._beta = beta;
21886 }
21887
21888 Bundle.prototype = {
21889   lineStart: function() {
21890     this._x = [];
21891     this._y = [];
21892     this._basis.lineStart();
21893   },
21894   lineEnd: function() {
21895     var x = this._x,
21896         y = this._y,
21897         j = x.length - 1;
21898
21899     if (j > 0) {
21900       var x0 = x[0],
21901           y0 = y[0],
21902           dx = x[j] - x0,
21903           dy = y[j] - y0,
21904           i = -1,
21905           t;
21906
21907       while (++i <= j) {
21908         t = i / j;
21909         this._basis.point(
21910           this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
21911           this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
21912         );
21913       }
21914     }
21915
21916     this._x = this._y = null;
21917     this._basis.lineEnd();
21918   },
21919   point: function(x, y) {
21920     this._x.push(+x);
21921     this._y.push(+y);
21922   }
21923 };
21924
21925 var bundle = (function custom(beta) {
21926
21927   function bundle(context) {
21928     return beta === 1 ? new Basis(context) : new Bundle(context, beta);
21929   }
21930
21931   bundle.beta = function(beta) {
21932     return custom(+beta);
21933   };
21934
21935   return bundle;
21936 })(0.85);
21937
21938 function point$1(that, x, y) {
21939   that._context.bezierCurveTo(
21940     that._x1 + that._k * (that._x2 - that._x0),
21941     that._y1 + that._k * (that._y2 - that._y0),
21942     that._x2 + that._k * (that._x1 - x),
21943     that._y2 + that._k * (that._y1 - y),
21944     that._x2,
21945     that._y2
21946   );
21947 }
21948
21949 function Cardinal(context, tension) {
21950   this._context = context;
21951   this._k = (1 - tension) / 6;
21952 }
21953
21954 Cardinal.prototype = {
21955   areaStart: function() {
21956     this._line = 0;
21957   },
21958   areaEnd: function() {
21959     this._line = NaN;
21960   },
21961   lineStart: function() {
21962     this._x0 = this._x1 = this._x2 =
21963     this._y0 = this._y1 = this._y2 = NaN;
21964     this._point = 0;
21965   },
21966   lineEnd: function() {
21967     switch (this._point) {
21968       case 2: this._context.lineTo(this._x2, this._y2); break;
21969       case 3: point$1(this, this._x1, this._y1); break;
21970     }
21971     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21972     this._line = 1 - this._line;
21973   },
21974   point: function(x, y) {
21975     x = +x, y = +y;
21976     switch (this._point) {
21977       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21978       case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
21979       case 2: this._point = 3; // proceed
21980       default: point$1(this, x, y); break;
21981     }
21982     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
21983     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
21984   }
21985 };
21986
21987 var cardinal = (function custom(tension) {
21988
21989   function cardinal(context) {
21990     return new Cardinal(context, tension);
21991   }
21992
21993   cardinal.tension = function(tension) {
21994     return custom(+tension);
21995   };
21996
21997   return cardinal;
21998 })(0);
21999
22000 function CardinalClosed(context, tension) {
22001   this._context = context;
22002   this._k = (1 - tension) / 6;
22003 }
22004
22005 CardinalClosed.prototype = {
22006   areaStart: noop,
22007   areaEnd: noop,
22008   lineStart: function() {
22009     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
22010     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
22011     this._point = 0;
22012   },
22013   lineEnd: function() {
22014     switch (this._point) {
22015       case 1: {
22016         this._context.moveTo(this._x3, this._y3);
22017         this._context.closePath();
22018         break;
22019       }
22020       case 2: {
22021         this._context.lineTo(this._x3, this._y3);
22022         this._context.closePath();
22023         break;
22024       }
22025       case 3: {
22026         this.point(this._x3, this._y3);
22027         this.point(this._x4, this._y4);
22028         this.point(this._x5, this._y5);
22029         break;
22030       }
22031     }
22032   },
22033   point: function(x, y) {
22034     x = +x, y = +y;
22035     switch (this._point) {
22036       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
22037       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
22038       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
22039       default: point$1(this, x, y); break;
22040     }
22041     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22042     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22043   }
22044 };
22045
22046 var cardinalClosed = (function custom(tension) {
22047
22048   function cardinal(context) {
22049     return new CardinalClosed(context, tension);
22050   }
22051
22052   cardinal.tension = function(tension) {
22053     return custom(+tension);
22054   };
22055
22056   return cardinal;
22057 })(0);
22058
22059 function CardinalOpen(context, tension) {
22060   this._context = context;
22061   this._k = (1 - tension) / 6;
22062 }
22063
22064 CardinalOpen.prototype = {
22065   areaStart: function() {
22066     this._line = 0;
22067   },
22068   areaEnd: function() {
22069     this._line = NaN;
22070   },
22071   lineStart: function() {
22072     this._x0 = this._x1 = this._x2 =
22073     this._y0 = this._y1 = this._y2 = NaN;
22074     this._point = 0;
22075   },
22076   lineEnd: function() {
22077     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
22078     this._line = 1 - this._line;
22079   },
22080   point: function(x, y) {
22081     x = +x, y = +y;
22082     switch (this._point) {
22083       case 0: this._point = 1; break;
22084       case 1: this._point = 2; break;
22085       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
22086       case 3: this._point = 4; // proceed
22087       default: point$1(this, x, y); break;
22088     }
22089     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22090     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22091   }
22092 };
22093
22094 var cardinalOpen = (function custom(tension) {
22095
22096   function cardinal(context) {
22097     return new CardinalOpen(context, tension);
22098   }
22099
22100   cardinal.tension = function(tension) {
22101     return custom(+tension);
22102   };
22103
22104   return cardinal;
22105 })(0);
22106
22107 function point$2(that, x, y) {
22108   var x1 = that._x1,
22109       y1 = that._y1,
22110       x2 = that._x2,
22111       y2 = that._y2;
22112
22113   if (that._l01_a > epsilon$1) {
22114     var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
22115         n = 3 * that._l01_a * (that._l01_a + that._l12_a);
22116     x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
22117     y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
22118   }
22119
22120   if (that._l23_a > epsilon$1) {
22121     var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
22122         m = 3 * that._l23_a * (that._l23_a + that._l12_a);
22123     x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
22124     y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
22125   }
22126
22127   that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
22128 }
22129
22130 function CatmullRom(context, alpha) {
22131   this._context = context;
22132   this._alpha = alpha;
22133 }
22134
22135 CatmullRom.prototype = {
22136   areaStart: function() {
22137     this._line = 0;
22138   },
22139   areaEnd: function() {
22140     this._line = NaN;
22141   },
22142   lineStart: function() {
22143     this._x0 = this._x1 = this._x2 =
22144     this._y0 = this._y1 = this._y2 = NaN;
22145     this._l01_a = this._l12_a = this._l23_a =
22146     this._l01_2a = this._l12_2a = this._l23_2a =
22147     this._point = 0;
22148   },
22149   lineEnd: function() {
22150     switch (this._point) {
22151       case 2: this._context.lineTo(this._x2, this._y2); break;
22152       case 3: this.point(this._x2, this._y2); break;
22153     }
22154     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22155     this._line = 1 - this._line;
22156   },
22157   point: function(x, y) {
22158     x = +x, y = +y;
22159
22160     if (this._point) {
22161       var x23 = this._x2 - x,
22162           y23 = this._y2 - y;
22163       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22164     }
22165
22166     switch (this._point) {
22167       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22168       case 1: this._point = 2; break;
22169       case 2: this._point = 3; // proceed
22170       default: point$2(this, x, y); break;
22171     }
22172
22173     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22174     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22175     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22176     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22177   }
22178 };
22179
22180 var catmullRom = (function custom(alpha) {
22181
22182   function catmullRom(context) {
22183     return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
22184   }
22185
22186   catmullRom.alpha = function(alpha) {
22187     return custom(+alpha);
22188   };
22189
22190   return catmullRom;
22191 })(0.5);
22192
22193 function CatmullRomClosed(context, alpha) {
22194   this._context = context;
22195   this._alpha = alpha;
22196 }
22197
22198 CatmullRomClosed.prototype = {
22199   areaStart: noop,
22200   areaEnd: noop,
22201   lineStart: function() {
22202     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
22203     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
22204     this._l01_a = this._l12_a = this._l23_a =
22205     this._l01_2a = this._l12_2a = this._l23_2a =
22206     this._point = 0;
22207   },
22208   lineEnd: function() {
22209     switch (this._point) {
22210       case 1: {
22211         this._context.moveTo(this._x3, this._y3);
22212         this._context.closePath();
22213         break;
22214       }
22215       case 2: {
22216         this._context.lineTo(this._x3, this._y3);
22217         this._context.closePath();
22218         break;
22219       }
22220       case 3: {
22221         this.point(this._x3, this._y3);
22222         this.point(this._x4, this._y4);
22223         this.point(this._x5, this._y5);
22224         break;
22225       }
22226     }
22227   },
22228   point: function(x, y) {
22229     x = +x, y = +y;
22230
22231     if (this._point) {
22232       var x23 = this._x2 - x,
22233           y23 = this._y2 - y;
22234       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22235     }
22236
22237     switch (this._point) {
22238       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
22239       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
22240       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
22241       default: point$2(this, x, y); break;
22242     }
22243
22244     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22245     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22246     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22247     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22248   }
22249 };
22250
22251 var catmullRomClosed = (function custom(alpha) {
22252
22253   function catmullRom(context) {
22254     return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
22255   }
22256
22257   catmullRom.alpha = function(alpha) {
22258     return custom(+alpha);
22259   };
22260
22261   return catmullRom;
22262 })(0.5);
22263
22264 function CatmullRomOpen(context, alpha) {
22265   this._context = context;
22266   this._alpha = alpha;
22267 }
22268
22269 CatmullRomOpen.prototype = {
22270   areaStart: function() {
22271     this._line = 0;
22272   },
22273   areaEnd: function() {
22274     this._line = NaN;
22275   },
22276   lineStart: function() {
22277     this._x0 = this._x1 = this._x2 =
22278     this._y0 = this._y1 = this._y2 = NaN;
22279     this._l01_a = this._l12_a = this._l23_a =
22280     this._l01_2a = this._l12_2a = this._l23_2a =
22281     this._point = 0;
22282   },
22283   lineEnd: function() {
22284     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
22285     this._line = 1 - this._line;
22286   },
22287   point: function(x, y) {
22288     x = +x, y = +y;
22289
22290     if (this._point) {
22291       var x23 = this._x2 - x,
22292           y23 = this._y2 - y;
22293       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22294     }
22295
22296     switch (this._point) {
22297       case 0: this._point = 1; break;
22298       case 1: this._point = 2; break;
22299       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
22300       case 3: this._point = 4; // proceed
22301       default: point$2(this, x, y); break;
22302     }
22303
22304     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22305     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22306     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22307     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22308   }
22309 };
22310
22311 var catmullRomOpen = (function custom(alpha) {
22312
22313   function catmullRom(context) {
22314     return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
22315   }
22316
22317   catmullRom.alpha = function(alpha) {
22318     return custom(+alpha);
22319   };
22320
22321   return catmullRom;
22322 })(0.5);
22323
22324 function LinearClosed(context) {
22325   this._context = context;
22326 }
22327
22328 LinearClosed.prototype = {
22329   areaStart: noop,
22330   areaEnd: noop,
22331   lineStart: function() {
22332     this._point = 0;
22333   },
22334   lineEnd: function() {
22335     if (this._point) this._context.closePath();
22336   },
22337   point: function(x, y) {
22338     x = +x, y = +y;
22339     if (this._point) this._context.lineTo(x, y);
22340     else this._point = 1, this._context.moveTo(x, y);
22341   }
22342 };
22343
22344 var linearClosed = function(context) {
22345   return new LinearClosed(context);
22346 };
22347
22348 function sign(x) {
22349   return x < 0 ? -1 : 1;
22350 }
22351
22352 // Calculate the slopes of the tangents (Hermite-type interpolation) based on
22353 // the following paper: Steffen, M. 1990. A Simple Method for Monotonic
22354 // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
22355 // NOV(II), P. 443, 1990.
22356 function slope3(that, x2, y2) {
22357   var h0 = that._x1 - that._x0,
22358       h1 = x2 - that._x1,
22359       s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
22360       s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
22361       p = (s0 * h1 + s1 * h0) / (h0 + h1);
22362   return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
22363 }
22364
22365 // Calculate a one-sided slope.
22366 function slope2(that, t) {
22367   var h = that._x1 - that._x0;
22368   return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
22369 }
22370
22371 // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
22372 // "you can express cubic Hermite interpolation in terms of cubic Bézier curves
22373 // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
22374 function point$3(that, t0, t1) {
22375   var x0 = that._x0,
22376       y0 = that._y0,
22377       x1 = that._x1,
22378       y1 = that._y1,
22379       dx = (x1 - x0) / 3;
22380   that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
22381 }
22382
22383 function MonotoneX(context) {
22384   this._context = context;
22385 }
22386
22387 MonotoneX.prototype = {
22388   areaStart: function() {
22389     this._line = 0;
22390   },
22391   areaEnd: function() {
22392     this._line = NaN;
22393   },
22394   lineStart: function() {
22395     this._x0 = this._x1 =
22396     this._y0 = this._y1 =
22397     this._t0 = NaN;
22398     this._point = 0;
22399   },
22400   lineEnd: function() {
22401     switch (this._point) {
22402       case 2: this._context.lineTo(this._x1, this._y1); break;
22403       case 3: point$3(this, this._t0, slope2(this, this._t0)); break;
22404     }
22405     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22406     this._line = 1 - this._line;
22407   },
22408   point: function(x, y) {
22409     var t1 = NaN;
22410
22411     x = +x, y = +y;
22412     if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
22413     switch (this._point) {
22414       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22415       case 1: this._point = 2; break;
22416       case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
22417       default: point$3(this, this._t0, t1 = slope3(this, x, y)); break;
22418     }
22419
22420     this._x0 = this._x1, this._x1 = x;
22421     this._y0 = this._y1, this._y1 = y;
22422     this._t0 = t1;
22423   }
22424 };
22425
22426 function MonotoneY(context) {
22427   this._context = new ReflectContext(context);
22428 }
22429
22430 (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
22431   MonotoneX.prototype.point.call(this, y, x);
22432 };
22433
22434 function ReflectContext(context) {
22435   this._context = context;
22436 }
22437
22438 ReflectContext.prototype = {
22439   moveTo: function(x, y) { this._context.moveTo(y, x); },
22440   closePath: function() { this._context.closePath(); },
22441   lineTo: function(x, y) { this._context.lineTo(y, x); },
22442   bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
22443 };
22444
22445 function monotoneX(context) {
22446   return new MonotoneX(context);
22447 }
22448
22449 function monotoneY(context) {
22450   return new MonotoneY(context);
22451 }
22452
22453 function Natural(context) {
22454   this._context = context;
22455 }
22456
22457 Natural.prototype = {
22458   areaStart: function() {
22459     this._line = 0;
22460   },
22461   areaEnd: function() {
22462     this._line = NaN;
22463   },
22464   lineStart: function() {
22465     this._x = [];
22466     this._y = [];
22467   },
22468   lineEnd: function() {
22469     var x = this._x,
22470         y = this._y,
22471         n = x.length;
22472
22473     if (n) {
22474       this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
22475       if (n === 2) {
22476         this._context.lineTo(x[1], y[1]);
22477       } else {
22478         var px = controlPoints(x),
22479             py = controlPoints(y);
22480         for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
22481           this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
22482         }
22483       }
22484     }
22485
22486     if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
22487     this._line = 1 - this._line;
22488     this._x = this._y = null;
22489   },
22490   point: function(x, y) {
22491     this._x.push(+x);
22492     this._y.push(+y);
22493   }
22494 };
22495
22496 // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
22497 function controlPoints(x) {
22498   var i,
22499       n = x.length - 1,
22500       m,
22501       a = new Array(n),
22502       b = new Array(n),
22503       r = new Array(n);
22504   a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
22505   for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
22506   a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
22507   for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
22508   a[n - 1] = r[n - 1] / b[n - 1];
22509   for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
22510   b[n - 1] = (x[n] + a[n - 1]) / 2;
22511   for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
22512   return [a, b];
22513 }
22514
22515 var natural = function(context) {
22516   return new Natural(context);
22517 };
22518
22519 function Step(context, t) {
22520   this._context = context;
22521   this._t = t;
22522 }
22523
22524 Step.prototype = {
22525   areaStart: function() {
22526     this._line = 0;
22527   },
22528   areaEnd: function() {
22529     this._line = NaN;
22530   },
22531   lineStart: function() {
22532     this._x = this._y = NaN;
22533     this._point = 0;
22534   },
22535   lineEnd: function() {
22536     if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
22537     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22538     if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
22539   },
22540   point: function(x, y) {
22541     x = +x, y = +y;
22542     switch (this._point) {
22543       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22544       case 1: this._point = 2; // proceed
22545       default: {
22546         if (this._t <= 0) {
22547           this._context.lineTo(this._x, y);
22548           this._context.lineTo(x, y);
22549         } else {
22550           var x1 = this._x * (1 - this._t) + x * this._t;
22551           this._context.lineTo(x1, this._y);
22552           this._context.lineTo(x1, y);
22553         }
22554         break;
22555       }
22556     }
22557     this._x = x, this._y = y;
22558   }
22559 };
22560
22561 var step = function(context) {
22562   return new Step(context, 0.5);
22563 };
22564
22565 function stepBefore(context) {
22566   return new Step(context, 0);
22567 }
22568
22569 function stepAfter(context) {
22570   return new Step(context, 1);
22571 }
22572
22573 var slice$2 = Array.prototype.slice;
22574
22575 var none = function(series, order) {
22576   if (!((n = series.length) > 1)) return;
22577   for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
22578     s0 = s1, s1 = series[order[i]];
22579     for (var j = 0; j < m; ++j) {
22580       s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
22581     }
22582   }
22583 };
22584
22585 var none$1 = function(series) {
22586   var n = series.length, o = new Array(n);
22587   while (--n >= 0) o[n] = n;
22588   return o;
22589 };
22590
22591 function stackValue(d, key) {
22592   return d[key];
22593 }
22594
22595 var stack = function() {
22596   var keys = constant$2([]),
22597       order = none$1,
22598       offset = none,
22599       value = stackValue;
22600
22601   function stack(data) {
22602     var kz = keys.apply(this, arguments),
22603         i,
22604         m = data.length,
22605         n = kz.length,
22606         sz = new Array(n),
22607         oz;
22608
22609     for (i = 0; i < n; ++i) {
22610       for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
22611         si[j] = sij = [0, +value(data[j], ki, j, data)];
22612         sij.data = data[j];
22613       }
22614       si.key = ki;
22615     }
22616
22617     for (i = 0, oz = order(sz); i < n; ++i) {
22618       sz[oz[i]].index = i;
22619     }
22620
22621     offset(sz, oz);
22622     return sz;
22623   }
22624
22625   stack.keys = function(_) {
22626     return arguments.length ? (keys = typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : keys;
22627   };
22628
22629   stack.value = function(_) {
22630     return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), stack) : value;
22631   };
22632
22633   stack.order = function(_) {
22634     return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : order;
22635   };
22636
22637   stack.offset = function(_) {
22638     return arguments.length ? (offset = _ == null ? none : _, stack) : offset;
22639   };
22640
22641   return stack;
22642 };
22643
22644 var expand = function(series, order) {
22645   if (!((n = series.length) > 0)) return;
22646   for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
22647     for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
22648     if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
22649   }
22650   none(series, order);
22651 };
22652
22653 var silhouette = function(series, order) {
22654   if (!((n = series.length) > 0)) return;
22655   for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
22656     for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
22657     s0[j][1] += s0[j][0] = -y / 2;
22658   }
22659   none(series, order);
22660 };
22661
22662 var wiggle = function(series, order) {
22663   if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
22664   for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
22665     for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
22666       var si = series[order[i]],
22667           sij0 = si[j][1] || 0,
22668           sij1 = si[j - 1][1] || 0,
22669           s3 = (sij0 - sij1) / 2;
22670       for (var k = 0; k < i; ++k) {
22671         var sk = series[order[k]],
22672             skj0 = sk[j][1] || 0,
22673             skj1 = sk[j - 1][1] || 0;
22674         s3 += skj0 - skj1;
22675       }
22676       s1 += sij0, s2 += s3 * sij0;
22677     }
22678     s0[j - 1][1] += s0[j - 1][0] = y;
22679     if (s1) y -= s2 / s1;
22680   }
22681   s0[j - 1][1] += s0[j - 1][0] = y;
22682   none(series, order);
22683 };
22684
22685 var ascending$1 = function(series) {
22686   var sums = series.map(sum$1);
22687   return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; });
22688 };
22689
22690 function sum$1(series) {
22691   var s = 0, i = -1, n = series.length, v;
22692   while (++i < n) if (v = +series[i][1]) s += v;
22693   return s;
22694 }
22695
22696 var descending$2 = function(series) {
22697   return ascending$1(series).reverse();
22698 };
22699
22700 var insideOut = function(series) {
22701   var n = series.length,
22702       i,
22703       j,
22704       sums = series.map(sum$1),
22705       order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }),
22706       top = 0,
22707       bottom = 0,
22708       tops = [],
22709       bottoms = [];
22710
22711   for (i = 0; i < n; ++i) {
22712     j = order[i];
22713     if (top < bottom) {
22714       top += sums[j];
22715       tops.push(j);
22716     } else {
22717       bottom += sums[j];
22718       bottoms.push(j);
22719     }
22720   }
22721
22722   return bottoms.reverse().concat(tops);
22723 };
22724
22725 var reverse = function(series) {
22726   return none$1(series).reverse();
22727 };
22728
22729 var define$1 = function(constructor, factory, prototype) {
22730   constructor.prototype = factory.prototype = prototype;
22731   prototype.constructor = constructor;
22732 };
22733
22734 function extend(parent, definition) {
22735   var prototype = Object.create(parent.prototype);
22736   for (var key in definition) prototype[key] = definition[key];
22737   return prototype;
22738 }
22739
22740 function Color() {}
22741
22742 var darker = 0.7;
22743 var brighter = 1 / darker;
22744
22745 var reI = "\\s*([+-]?\\d+)\\s*";
22746 var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*";
22747 var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*";
22748 var reHex3 = /^#([0-9a-f]{3})$/;
22749 var reHex6 = /^#([0-9a-f]{6})$/;
22750 var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$");
22751 var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$");
22752 var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$");
22753 var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$");
22754 var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$");
22755 var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
22756
22757 var named = {
22758   aliceblue: 0xf0f8ff,
22759   antiquewhite: 0xfaebd7,
22760   aqua: 0x00ffff,
22761   aquamarine: 0x7fffd4,
22762   azure: 0xf0ffff,
22763   beige: 0xf5f5dc,
22764   bisque: 0xffe4c4,
22765   black: 0x000000,
22766   blanchedalmond: 0xffebcd,
22767   blue: 0x0000ff,
22768   blueviolet: 0x8a2be2,
22769   brown: 0xa52a2a,
22770   burlywood: 0xdeb887,
22771   cadetblue: 0x5f9ea0,
22772   chartreuse: 0x7fff00,
22773   chocolate: 0xd2691e,
22774   coral: 0xff7f50,
22775   cornflowerblue: 0x6495ed,
22776   cornsilk: 0xfff8dc,
22777   crimson: 0xdc143c,
22778   cyan: 0x00ffff,
22779   darkblue: 0x00008b,
22780   darkcyan: 0x008b8b,
22781   darkgoldenrod: 0xb8860b,
22782   darkgray: 0xa9a9a9,
22783   darkgreen: 0x006400,
22784   darkgrey: 0xa9a9a9,
22785   darkkhaki: 0xbdb76b,
22786   darkmagenta: 0x8b008b,
22787   darkolivegreen: 0x556b2f,
22788   darkorange: 0xff8c00,
22789   darkorchid: 0x9932cc,
22790   darkred: 0x8b0000,
22791   darksalmon: 0xe9967a,
22792   darkseagreen: 0x8fbc8f,
22793   darkslateblue: 0x483d8b,
22794   darkslategray: 0x2f4f4f,
22795   darkslategrey: 0x2f4f4f,
22796   darkturquoise: 0x00ced1,
22797   darkviolet: 0x9400d3,
22798   deeppink: 0xff1493,
22799   deepskyblue: 0x00bfff,
22800   dimgray: 0x696969,
22801   dimgrey: 0x696969,
22802   dodgerblue: 0x1e90ff,
22803   firebrick: 0xb22222,
22804   floralwhite: 0xfffaf0,
22805   forestgreen: 0x228b22,
22806   fuchsia: 0xff00ff,
22807   gainsboro: 0xdcdcdc,
22808   ghostwhite: 0xf8f8ff,
22809   gold: 0xffd700,
22810   goldenrod: 0xdaa520,
22811   gray: 0x808080,
22812   green: 0x008000,
22813   greenyellow: 0xadff2f,
22814   grey: 0x808080,
22815   honeydew: 0xf0fff0,
22816   hotpink: 0xff69b4,
22817   indianred: 0xcd5c5c,
22818   indigo: 0x4b0082,
22819   ivory: 0xfffff0,
22820   khaki: 0xf0e68c,
22821   lavender: 0xe6e6fa,
22822   lavenderblush: 0xfff0f5,
22823   lawngreen: 0x7cfc00,
22824   lemonchiffon: 0xfffacd,
22825   lightblue: 0xadd8e6,
22826   lightcoral: 0xf08080,
22827   lightcyan: 0xe0ffff,
22828   lightgoldenrodyellow: 0xfafad2,
22829   lightgray: 0xd3d3d3,
22830   lightgreen: 0x90ee90,
22831   lightgrey: 0xd3d3d3,
22832   lightpink: 0xffb6c1,
22833   lightsalmon: 0xffa07a,
22834   lightseagreen: 0x20b2aa,
22835   lightskyblue: 0x87cefa,
22836   lightslategray: 0x778899,
22837   lightslategrey: 0x778899,
22838   lightsteelblue: 0xb0c4de,
22839   lightyellow: 0xffffe0,
22840   lime: 0x00ff00,
22841   limegreen: 0x32cd32,
22842   linen: 0xfaf0e6,
22843   magenta: 0xff00ff,
22844   maroon: 0x800000,
22845   mediumaquamarine: 0x66cdaa,
22846   mediumblue: 0x0000cd,
22847   mediumorchid: 0xba55d3,
22848   mediumpurple: 0x9370db,
22849   mediumseagreen: 0x3cb371,
22850   mediumslateblue: 0x7b68ee,
22851   mediumspringgreen: 0x00fa9a,
22852   mediumturquoise: 0x48d1cc,
22853   mediumvioletred: 0xc71585,
22854   midnightblue: 0x191970,
22855   mintcream: 0xf5fffa,
22856   mistyrose: 0xffe4e1,
22857   moccasin: 0xffe4b5,
22858   navajowhite: 0xffdead,
22859   navy: 0x000080,
22860   oldlace: 0xfdf5e6,
22861   olive: 0x808000,
22862   olivedrab: 0x6b8e23,
22863   orange: 0xffa500,
22864   orangered: 0xff4500,
22865   orchid: 0xda70d6,
22866   palegoldenrod: 0xeee8aa,
22867   palegreen: 0x98fb98,
22868   paleturquoise: 0xafeeee,
22869   palevioletred: 0xdb7093,
22870   papayawhip: 0xffefd5,
22871   peachpuff: 0xffdab9,
22872   peru: 0xcd853f,
22873   pink: 0xffc0cb,
22874   plum: 0xdda0dd,
22875   powderblue: 0xb0e0e6,
22876   purple: 0x800080,
22877   rebeccapurple: 0x663399,
22878   red: 0xff0000,
22879   rosybrown: 0xbc8f8f,
22880   royalblue: 0x4169e1,
22881   saddlebrown: 0x8b4513,
22882   salmon: 0xfa8072,
22883   sandybrown: 0xf4a460,
22884   seagreen: 0x2e8b57,
22885   seashell: 0xfff5ee,
22886   sienna: 0xa0522d,
22887   silver: 0xc0c0c0,
22888   skyblue: 0x87ceeb,
22889   slateblue: 0x6a5acd,
22890   slategray: 0x708090,
22891   slategrey: 0x708090,
22892   snow: 0xfffafa,
22893   springgreen: 0x00ff7f,
22894   steelblue: 0x4682b4,
22895   tan: 0xd2b48c,
22896   teal: 0x008080,
22897   thistle: 0xd8bfd8,
22898   tomato: 0xff6347,
22899   turquoise: 0x40e0d0,
22900   violet: 0xee82ee,
22901   wheat: 0xf5deb3,
22902   white: 0xffffff,
22903   whitesmoke: 0xf5f5f5,
22904   yellow: 0xffff00,
22905   yellowgreen: 0x9acd32
22906 };
22907
22908 define$1(Color, color, {
22909   displayable: function() {
22910     return this.rgb().displayable();
22911   },
22912   toString: function() {
22913     return this.rgb() + "";
22914   }
22915 });
22916
22917 function color(format) {
22918   var m;
22919   format = (format + "").trim().toLowerCase();
22920   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
22921       : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
22922       : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
22923       : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
22924       : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
22925       : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
22926       : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
22927       : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
22928       : named.hasOwnProperty(format) ? rgbn(named[format])
22929       : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
22930       : null;
22931 }
22932
22933 function rgbn(n) {
22934   return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
22935 }
22936
22937 function rgba(r, g, b, a) {
22938   if (a <= 0) r = g = b = NaN;
22939   return new Rgb(r, g, b, a);
22940 }
22941
22942 function rgbConvert(o) {
22943   if (!(o instanceof Color)) o = color(o);
22944   if (!o) return new Rgb;
22945   o = o.rgb();
22946   return new Rgb(o.r, o.g, o.b, o.opacity);
22947 }
22948
22949 function rgb(r, g, b, opacity) {
22950   return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
22951 }
22952
22953 function Rgb(r, g, b, opacity) {
22954   this.r = +r;
22955   this.g = +g;
22956   this.b = +b;
22957   this.opacity = +opacity;
22958 }
22959
22960 define$1(Rgb, rgb, extend(Color, {
22961   brighter: function(k) {
22962     k = k == null ? brighter : Math.pow(brighter, k);
22963     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
22964   },
22965   darker: function(k) {
22966     k = k == null ? darker : Math.pow(darker, k);
22967     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
22968   },
22969   rgb: function() {
22970     return this;
22971   },
22972   displayable: function() {
22973     return (0 <= this.r && this.r <= 255)
22974         && (0 <= this.g && this.g <= 255)
22975         && (0 <= this.b && this.b <= 255)
22976         && (0 <= this.opacity && this.opacity <= 1);
22977   },
22978   toString: function() {
22979     var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
22980     return (a === 1 ? "rgb(" : "rgba(")
22981         + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
22982         + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
22983         + Math.max(0, Math.min(255, Math.round(this.b) || 0))
22984         + (a === 1 ? ")" : ", " + a + ")");
22985   }
22986 }));
22987
22988 function hsla(h, s, l, a) {
22989   if (a <= 0) h = s = l = NaN;
22990   else if (l <= 0 || l >= 1) h = s = NaN;
22991   else if (s <= 0) h = NaN;
22992   return new Hsl(h, s, l, a);
22993 }
22994
22995 function hslConvert(o) {
22996   if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
22997   if (!(o instanceof Color)) o = color(o);
22998   if (!o) return new Hsl;
22999   if (o instanceof Hsl) return o;
23000   o = o.rgb();
23001   var r = o.r / 255,
23002       g = o.g / 255,
23003       b = o.b / 255,
23004       min = Math.min(r, g, b),
23005       max = Math.max(r, g, b),
23006       h = NaN,
23007       s = max - min,
23008       l = (max + min) / 2;
23009   if (s) {
23010     if (r === max) h = (g - b) / s + (g < b) * 6;
23011     else if (g === max) h = (b - r) / s + 2;
23012     else h = (r - g) / s + 4;
23013     s /= l < 0.5 ? max + min : 2 - max - min;
23014     h *= 60;
23015   } else {
23016     s = l > 0 && l < 1 ? 0 : h;
23017   }
23018   return new Hsl(h, s, l, o.opacity);
23019 }
23020
23021 function hsl(h, s, l, opacity) {
23022   return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
23023 }
23024
23025 function Hsl(h, s, l, opacity) {
23026   this.h = +h;
23027   this.s = +s;
23028   this.l = +l;
23029   this.opacity = +opacity;
23030 }
23031
23032 define$1(Hsl, hsl, extend(Color, {
23033   brighter: function(k) {
23034     k = k == null ? brighter : Math.pow(brighter, k);
23035     return new Hsl(this.h, this.s, this.l * k, this.opacity);
23036   },
23037   darker: function(k) {
23038     k = k == null ? darker : Math.pow(darker, k);
23039     return new Hsl(this.h, this.s, this.l * k, this.opacity);
23040   },
23041   rgb: function() {
23042     var h = this.h % 360 + (this.h < 0) * 360,
23043         s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
23044         l = this.l,
23045         m2 = l + (l < 0.5 ? l : 1 - l) * s,
23046         m1 = 2 * l - m2;
23047     return new Rgb(
23048       hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
23049       hsl2rgb(h, m1, m2),
23050       hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
23051       this.opacity
23052     );
23053   },
23054   displayable: function() {
23055     return (0 <= this.s && this.s <= 1 || isNaN(this.s))
23056         && (0 <= this.l && this.l <= 1)
23057         && (0 <= this.opacity && this.opacity <= 1);
23058   }
23059 }));
23060
23061 /* From FvD 13.37, CSS Color Module Level 3 */
23062 function hsl2rgb(h, m1, m2) {
23063   return (h < 60 ? m1 + (m2 - m1) * h / 60
23064       : h < 180 ? m2
23065       : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
23066       : m1) * 255;
23067 }
23068
23069 var deg2rad = Math.PI / 180;
23070 var rad2deg = 180 / Math.PI;
23071
23072 var Kn = 18;
23073 var Xn = 0.950470;
23074 var Yn = 1;
23075 var Zn = 1.088830;
23076 var t0 = 4 / 29;
23077 var t1 = 6 / 29;
23078 var t2 = 3 * t1 * t1;
23079 var t3 = t1 * t1 * t1;
23080
23081 function labConvert(o) {
23082   if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
23083   if (o instanceof Hcl) {
23084     var h = o.h * deg2rad;
23085     return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
23086   }
23087   if (!(o instanceof Rgb)) o = rgbConvert(o);
23088   var b = rgb2xyz(o.r),
23089       a = rgb2xyz(o.g),
23090       l = rgb2xyz(o.b),
23091       x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
23092       y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
23093       z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
23094   return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
23095 }
23096
23097 function lab(l, a, b, opacity) {
23098   return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
23099 }
23100
23101 function Lab(l, a, b, opacity) {
23102   this.l = +l;
23103   this.a = +a;
23104   this.b = +b;
23105   this.opacity = +opacity;
23106 }
23107
23108 define$1(Lab, lab, extend(Color, {
23109   brighter: function(k) {
23110     return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
23111   },
23112   darker: function(k) {
23113     return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
23114   },
23115   rgb: function() {
23116     var y = (this.l + 16) / 116,
23117         x = isNaN(this.a) ? y : y + this.a / 500,
23118         z = isNaN(this.b) ? y : y - this.b / 200;
23119     y = Yn * lab2xyz(y);
23120     x = Xn * lab2xyz(x);
23121     z = Zn * lab2xyz(z);
23122     return new Rgb(
23123       xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
23124       xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
23125       xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
23126       this.opacity
23127     );
23128   }
23129 }));
23130
23131 function xyz2lab(t) {
23132   return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
23133 }
23134
23135 function lab2xyz(t) {
23136   return t > t1 ? t * t * t : t2 * (t - t0);
23137 }
23138
23139 function xyz2rgb(x) {
23140   return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
23141 }
23142
23143 function rgb2xyz(x) {
23144   return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
23145 }
23146
23147 function hclConvert(o) {
23148   if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
23149   if (!(o instanceof Lab)) o = labConvert(o);
23150   var h = Math.atan2(o.b, o.a) * rad2deg;
23151   return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
23152 }
23153
23154 function hcl(h, c, l, opacity) {
23155   return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
23156 }
23157
23158 function Hcl(h, c, l, opacity) {
23159   this.h = +h;
23160   this.c = +c;
23161   this.l = +l;
23162   this.opacity = +opacity;
23163 }
23164
23165 define$1(Hcl, hcl, extend(Color, {
23166   brighter: function(k) {
23167     return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
23168   },
23169   darker: function(k) {
23170     return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
23171   },
23172   rgb: function() {
23173     return labConvert(this).rgb();
23174   }
23175 }));
23176
23177 var A = -0.14861;
23178 var B = +1.78277;
23179 var C = -0.29227;
23180 var D = -0.90649;
23181 var E = +1.97294;
23182 var ED = E * D;
23183 var EB = E * B;
23184 var BC_DA = B * C - D * A;
23185
23186 function cubehelixConvert(o) {
23187   if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
23188   if (!(o instanceof Rgb)) o = rgbConvert(o);
23189   var r = o.r / 255,
23190       g = o.g / 255,
23191       b = o.b / 255,
23192       l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
23193       bl = b - l,
23194       k = (E * (g - l) - C * bl) / D,
23195       s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
23196       h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
23197   return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
23198 }
23199
23200 function cubehelix(h, s, l, opacity) {
23201   return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
23202 }
23203
23204 function Cubehelix(h, s, l, opacity) {
23205   this.h = +h;
23206   this.s = +s;
23207   this.l = +l;
23208   this.opacity = +opacity;
23209 }
23210
23211 define$1(Cubehelix, cubehelix, extend(Color, {
23212   brighter: function(k) {
23213     k = k == null ? brighter : Math.pow(brighter, k);
23214     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
23215   },
23216   darker: function(k) {
23217     k = k == null ? darker : Math.pow(darker, k);
23218     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
23219   },
23220   rgb: function() {
23221     var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
23222         l = +this.l,
23223         a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
23224         cosh = Math.cos(h),
23225         sinh = Math.sin(h);
23226     return new Rgb(
23227       255 * (l + a * (A * cosh + B * sinh)),
23228       255 * (l + a * (C * cosh + D * sinh)),
23229       255 * (l + a * (E * cosh)),
23230       this.opacity
23231     );
23232   }
23233 }));
23234
23235 function basis$1(t1, v0, v1, v2, v3) {
23236   var t2 = t1 * t1, t3 = t2 * t1;
23237   return ((1 - 3 * t1 + 3 * t2 - t3) * v0
23238       + (4 - 6 * t2 + 3 * t3) * v1
23239       + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
23240       + t3 * v3) / 6;
23241 }
23242
23243 var basis$2 = function(values) {
23244   var n = values.length - 1;
23245   return function(t) {
23246     var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
23247         v1 = values[i],
23248         v2 = values[i + 1],
23249         v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
23250         v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
23251     return basis$1((t - i / n) * n, v0, v1, v2, v3);
23252   };
23253 };
23254
23255 var basisClosed$1 = function(values) {
23256   var n = values.length;
23257   return function(t) {
23258     var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
23259         v0 = values[(i + n - 1) % n],
23260         v1 = values[i % n],
23261         v2 = values[(i + 1) % n],
23262         v3 = values[(i + 2) % n];
23263     return basis$1((t - i / n) * n, v0, v1, v2, v3);
23264   };
23265 };
23266
23267 var constant$3 = function(x) {
23268   return function() {
23269     return x;
23270   };
23271 };
23272
23273 function linear$1(a, d) {
23274   return function(t) {
23275     return a + t * d;
23276   };
23277 }
23278
23279 function exponential$1(a, b, y) {
23280   return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
23281     return Math.pow(a + t * b, y);
23282   };
23283 }
23284
23285 function hue(a, b) {
23286   var d = b - a;
23287   return d ? linear$1(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
23288 }
23289
23290 function gamma(y) {
23291   return (y = +y) === 1 ? nogamma : function(a, b) {
23292     return b - a ? exponential$1(a, b, y) : constant$3(isNaN(a) ? b : a);
23293   };
23294 }
23295
23296 function nogamma(a, b) {
23297   var d = b - a;
23298   return d ? linear$1(a, d) : constant$3(isNaN(a) ? b : a);
23299 }
23300
23301 var interpolateRgb = (function rgbGamma(y) {
23302   var color$$1 = gamma(y);
23303
23304   function rgb$$1(start, end) {
23305     var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
23306         g = color$$1(start.g, end.g),
23307         b = color$$1(start.b, end.b),
23308         opacity = color$$1(start.opacity, end.opacity);
23309     return function(t) {
23310       start.r = r(t);
23311       start.g = g(t);
23312       start.b = b(t);
23313       start.opacity = opacity(t);
23314       return start + "";
23315     };
23316   }
23317
23318   rgb$$1.gamma = rgbGamma;
23319
23320   return rgb$$1;
23321 })(1);
23322
23323 function rgbSpline(spline) {
23324   return function(colors) {
23325     var n = colors.length,
23326         r = new Array(n),
23327         g = new Array(n),
23328         b = new Array(n),
23329         i, color$$1;
23330     for (i = 0; i < n; ++i) {
23331       color$$1 = rgb(colors[i]);
23332       r[i] = color$$1.r || 0;
23333       g[i] = color$$1.g || 0;
23334       b[i] = color$$1.b || 0;
23335     }
23336     r = spline(r);
23337     g = spline(g);
23338     b = spline(b);
23339     color$$1.opacity = 1;
23340     return function(t) {
23341       color$$1.r = r(t);
23342       color$$1.g = g(t);
23343       color$$1.b = b(t);
23344       return color$$1 + "";
23345     };
23346   };
23347 }
23348
23349 var rgbBasis = rgbSpline(basis$2);
23350 var rgbBasisClosed = rgbSpline(basisClosed$1);
23351
23352 var array$1 = function(a, b) {
23353   var nb = b ? b.length : 0,
23354       na = a ? Math.min(nb, a.length) : 0,
23355       x = new Array(nb),
23356       c = new Array(nb),
23357       i;
23358
23359   for (i = 0; i < na; ++i) x[i] = interpolate(a[i], b[i]);
23360   for (; i < nb; ++i) c[i] = b[i];
23361
23362   return function(t) {
23363     for (i = 0; i < na; ++i) c[i] = x[i](t);
23364     return c;
23365   };
23366 };
23367
23368 var date = function(a, b) {
23369   var d = new Date;
23370   return a = +a, b -= a, function(t) {
23371     return d.setTime(a + b * t), d;
23372   };
23373 };
23374
23375 var interpolateNumber = function(a, b) {
23376   return a = +a, b -= a, function(t) {
23377     return a + b * t;
23378   };
23379 };
23380
23381 var object = function(a, b) {
23382   var i = {},
23383       c = {},
23384       k;
23385
23386   if (a === null || typeof a !== "object") a = {};
23387   if (b === null || typeof b !== "object") b = {};
23388
23389   for (k in b) {
23390     if (k in a) {
23391       i[k] = interpolate(a[k], b[k]);
23392     } else {
23393       c[k] = b[k];
23394     }
23395   }
23396
23397   return function(t) {
23398     for (k in i) c[k] = i[k](t);
23399     return c;
23400   };
23401 };
23402
23403 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
23404 var reB = new RegExp(reA.source, "g");
23405
23406 function zero(b) {
23407   return function() {
23408     return b;
23409   };
23410 }
23411
23412 function one(b) {
23413   return function(t) {
23414     return b(t) + "";
23415   };
23416 }
23417
23418 var interpolateString = function(a, b) {
23419   var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
23420       am, // current match in a
23421       bm, // current match in b
23422       bs, // string preceding current number in b, if any
23423       i = -1, // index in s
23424       s = [], // string constants and placeholders
23425       q = []; // number interpolators
23426
23427   // Coerce inputs to strings.
23428   a = a + "", b = b + "";
23429
23430   // Interpolate pairs of numbers in a & b.
23431   while ((am = reA.exec(a))
23432       && (bm = reB.exec(b))) {
23433     if ((bs = bm.index) > bi) { // a string precedes the next number in b
23434       bs = b.slice(bi, bs);
23435       if (s[i]) s[i] += bs; // coalesce with previous string
23436       else s[++i] = bs;
23437     }
23438     if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
23439       if (s[i]) s[i] += bm; // coalesce with previous string
23440       else s[++i] = bm;
23441     } else { // interpolate non-matching numbers
23442       s[++i] = null;
23443       q.push({i: i, x: interpolateNumber(am, bm)});
23444     }
23445     bi = reB.lastIndex;
23446   }
23447
23448   // Add remains of b.
23449   if (bi < b.length) {
23450     bs = b.slice(bi);
23451     if (s[i]) s[i] += bs; // coalesce with previous string
23452     else s[++i] = bs;
23453   }
23454
23455   // Special optimization for only a single match.
23456   // Otherwise, interpolate each of the numbers and rejoin the string.
23457   return s.length < 2 ? (q[0]
23458       ? one(q[0].x)
23459       : zero(b))
23460       : (b = q.length, function(t) {
23461           for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
23462           return s.join("");
23463         });
23464 };
23465
23466 var interpolate = function(a, b) {
23467   var t = typeof b, c;
23468   return b == null || t === "boolean" ? constant$3(b)
23469       : (t === "number" ? interpolateNumber
23470       : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString)
23471       : b instanceof color ? interpolateRgb
23472       : b instanceof Date ? date
23473       : Array.isArray(b) ? array$1
23474       : isNaN(b) ? object
23475       : interpolateNumber)(a, b);
23476 };
23477
23478 var interpolateRound = function(a, b) {
23479   return a = +a, b -= a, function(t) {
23480     return Math.round(a + b * t);
23481   };
23482 };
23483
23484 var degrees = 180 / Math.PI;
23485
23486 var identity$2 = {
23487   translateX: 0,
23488   translateY: 0,
23489   rotate: 0,
23490   skewX: 0,
23491   scaleX: 1,
23492   scaleY: 1
23493 };
23494
23495 var decompose = function(a, b, c, d, e, f) {
23496   var scaleX, scaleY, skewX;
23497   if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
23498   if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
23499   if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
23500   if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
23501   return {
23502     translateX: e,
23503     translateY: f,
23504     rotate: Math.atan2(b, a) * degrees,
23505     skewX: Math.atan(skewX) * degrees,
23506     scaleX: scaleX,
23507     scaleY: scaleY
23508   };
23509 };
23510
23511 var cssNode;
23512 var cssRoot;
23513 var cssView;
23514 var svgNode;
23515
23516 function parseCss(value) {
23517   if (value === "none") return identity$2;
23518   if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
23519   cssNode.style.transform = value;
23520   value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
23521   cssRoot.removeChild(cssNode);
23522   value = value.slice(7, -1).split(",");
23523   return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
23524 }
23525
23526 function parseSvg(value) {
23527   if (value == null) return identity$2;
23528   if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
23529   svgNode.setAttribute("transform", value);
23530   if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2;
23531   value = value.matrix;
23532   return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
23533 }
23534
23535 function interpolateTransform(parse, pxComma, pxParen, degParen) {
23536
23537   function pop(s) {
23538     return s.length ? s.pop() + " " : "";
23539   }
23540
23541   function translate(xa, ya, xb, yb, s, q) {
23542     if (xa !== xb || ya !== yb) {
23543       var i = s.push("translate(", null, pxComma, null, pxParen);
23544       q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)});
23545     } else if (xb || yb) {
23546       s.push("translate(" + xb + pxComma + yb + pxParen);
23547     }
23548   }
23549
23550   function rotate(a, b, s, q) {
23551     if (a !== b) {
23552       if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
23553       q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)});
23554     } else if (b) {
23555       s.push(pop(s) + "rotate(" + b + degParen);
23556     }
23557   }
23558
23559   function skewX(a, b, s, q) {
23560     if (a !== b) {
23561       q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)});
23562     } else if (b) {
23563       s.push(pop(s) + "skewX(" + b + degParen);
23564     }
23565   }
23566
23567   function scale(xa, ya, xb, yb, s, q) {
23568     if (xa !== xb || ya !== yb) {
23569       var i = s.push(pop(s) + "scale(", null, ",", null, ")");
23570       q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)});
23571     } else if (xb !== 1 || yb !== 1) {
23572       s.push(pop(s) + "scale(" + xb + "," + yb + ")");
23573     }
23574   }
23575
23576   return function(a, b) {
23577     var s = [], // string constants and placeholders
23578         q = []; // number interpolators
23579     a = parse(a), b = parse(b);
23580     translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
23581     rotate(a.rotate, b.rotate, s, q);
23582     skewX(a.skewX, b.skewX, s, q);
23583     scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
23584     a = b = null; // gc
23585     return function(t) {
23586       var i = -1, n = q.length, o;
23587       while (++i < n) s[(o = q[i]).i] = o.x(t);
23588       return s.join("");
23589     };
23590   };
23591 }
23592
23593 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
23594 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
23595
23596 var rho = Math.SQRT2;
23597 var rho2 = 2;
23598 var rho4 = 4;
23599 var epsilon2 = 1e-12;
23600
23601 function cosh(x) {
23602   return ((x = Math.exp(x)) + 1 / x) / 2;
23603 }
23604
23605 function sinh(x) {
23606   return ((x = Math.exp(x)) - 1 / x) / 2;
23607 }
23608
23609 function tanh(x) {
23610   return ((x = Math.exp(2 * x)) - 1) / (x + 1);
23611 }
23612
23613 // p0 = [ux0, uy0, w0]
23614 // p1 = [ux1, uy1, w1]
23615 var interpolateZoom = function(p0, p1) {
23616   var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
23617       ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
23618       dx = ux1 - ux0,
23619       dy = uy1 - uy0,
23620       d2 = dx * dx + dy * dy,
23621       i,
23622       S;
23623
23624   // Special case for u0 ≅ u1.
23625   if (d2 < epsilon2) {
23626     S = Math.log(w1 / w0) / rho;
23627     i = function(t) {
23628       return [
23629         ux0 + t * dx,
23630         uy0 + t * dy,
23631         w0 * Math.exp(rho * t * S)
23632       ];
23633     };
23634   }
23635
23636   // General case.
23637   else {
23638     var d1 = Math.sqrt(d2),
23639         b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
23640         b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
23641         r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
23642         r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
23643     S = (r1 - r0) / rho;
23644     i = function(t) {
23645       var s = t * S,
23646           coshr0 = cosh(r0),
23647           u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
23648       return [
23649         ux0 + u * dx,
23650         uy0 + u * dy,
23651         w0 * coshr0 / cosh(rho * s + r0)
23652       ];
23653     };
23654   }
23655
23656   i.duration = S * 1000;
23657
23658   return i;
23659 };
23660
23661 function hsl$1(hue$$1) {
23662   return function(start, end) {
23663     var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h),
23664         s = nogamma(start.s, end.s),
23665         l = nogamma(start.l, end.l),
23666         opacity = nogamma(start.opacity, end.opacity);
23667     return function(t) {
23668       start.h = h(t);
23669       start.s = s(t);
23670       start.l = l(t);
23671       start.opacity = opacity(t);
23672       return start + "";
23673     };
23674   }
23675 }
23676
23677 var hsl$2 = hsl$1(hue);
23678 var hslLong = hsl$1(nogamma);
23679
23680 function lab$1(start, end) {
23681   var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
23682       a = nogamma(start.a, end.a),
23683       b = nogamma(start.b, end.b),
23684       opacity = nogamma(start.opacity, end.opacity);
23685   return function(t) {
23686     start.l = l(t);
23687     start.a = a(t);
23688     start.b = b(t);
23689     start.opacity = opacity(t);
23690     return start + "";
23691   };
23692 }
23693
23694 function hcl$1(hue$$1) {
23695   return function(start, end) {
23696     var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h),
23697         c = nogamma(start.c, end.c),
23698         l = nogamma(start.l, end.l),
23699         opacity = nogamma(start.opacity, end.opacity);
23700     return function(t) {
23701       start.h = h(t);
23702       start.c = c(t);
23703       start.l = l(t);
23704       start.opacity = opacity(t);
23705       return start + "";
23706     };
23707   }
23708 }
23709
23710 var hcl$2 = hcl$1(hue);
23711 var hclLong = hcl$1(nogamma);
23712
23713 function cubehelix$1(hue$$1) {
23714   return (function cubehelixGamma(y) {
23715     y = +y;
23716
23717     function cubehelix$$1(start, end) {
23718       var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
23719           s = nogamma(start.s, end.s),
23720           l = nogamma(start.l, end.l),
23721           opacity = nogamma(start.opacity, end.opacity);
23722       return function(t) {
23723         start.h = h(t);
23724         start.s = s(t);
23725         start.l = l(Math.pow(t, y));
23726         start.opacity = opacity(t);
23727         return start + "";
23728       };
23729     }
23730
23731     cubehelix$$1.gamma = cubehelixGamma;
23732
23733     return cubehelix$$1;
23734   })(1);
23735 }
23736
23737 var cubehelix$2 = cubehelix$1(hue);
23738 var cubehelixLong = cubehelix$1(nogamma);
23739
23740 var quantize = function(interpolator, n) {
23741   var samples = new Array(n);
23742   for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
23743   return samples;
23744 };
23745
23746 var noop$1 = {value: function() {}};
23747
23748 function dispatch() {
23749   for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
23750     if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
23751     _[t] = [];
23752   }
23753   return new Dispatch(_);
23754 }
23755
23756 function Dispatch(_) {
23757   this._ = _;
23758 }
23759
23760 function parseTypenames(typenames, types) {
23761   return typenames.trim().split(/^|\s+/).map(function(t) {
23762     var name = "", i = t.indexOf(".");
23763     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
23764     if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
23765     return {type: t, name: name};
23766   });
23767 }
23768
23769 Dispatch.prototype = dispatch.prototype = {
23770   constructor: Dispatch,
23771   on: function(typename, callback) {
23772     var _ = this._,
23773         T = parseTypenames(typename + "", _),
23774         t,
23775         i = -1,
23776         n = T.length;
23777
23778     // If no callback was specified, return the callback of the given type and name.
23779     if (arguments.length < 2) {
23780       while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
23781       return;
23782     }
23783
23784     // If a type was specified, set the callback for the given type and name.
23785     // Otherwise, if a null callback was specified, remove callbacks of the given name.
23786     if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
23787     while (++i < n) {
23788       if (t = (typename = T[i]).type) _[t] = set$2(_[t], typename.name, callback);
23789       else if (callback == null) for (t in _) _[t] = set$2(_[t], typename.name, null);
23790     }
23791
23792     return this;
23793   },
23794   copy: function() {
23795     var copy = {}, _ = this._;
23796     for (var t in _) copy[t] = _[t].slice();
23797     return new Dispatch(copy);
23798   },
23799   call: function(type, that) {
23800     if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
23801     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
23802     for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
23803   },
23804   apply: function(type, that, args) {
23805     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
23806     for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
23807   }
23808 };
23809
23810 function get(type, name) {
23811   for (var i = 0, n = type.length, c; i < n; ++i) {
23812     if ((c = type[i]).name === name) {
23813       return c.value;
23814     }
23815   }
23816 }
23817
23818 function set$2(type, name, callback) {
23819   for (var i = 0, n = type.length; i < n; ++i) {
23820     if (type[i].name === name) {
23821       type[i] = noop$1, type = type.slice(0, i).concat(type.slice(i + 1));
23822       break;
23823     }
23824   }
23825   if (callback != null) type.push({name: name, value: callback});
23826   return type;
23827 }
23828
23829 function objectConverter(columns) {
23830   return new Function("d", "return {" + columns.map(function(name, i) {
23831     return JSON.stringify(name) + ": d[" + i + "]";
23832   }).join(",") + "}");
23833 }
23834
23835 function customConverter(columns, f) {
23836   var object = objectConverter(columns);
23837   return function(row, i) {
23838     return f(object(row), i, columns);
23839   };
23840 }
23841
23842 // Compute unique columns in order of discovery.
23843 function inferColumns(rows) {
23844   var columnSet = Object.create(null),
23845       columns = [];
23846
23847   rows.forEach(function(row) {
23848     for (var column in row) {
23849       if (!(column in columnSet)) {
23850         columns.push(columnSet[column] = column);
23851       }
23852     }
23853   });
23854
23855   return columns;
23856 }
23857
23858 var dsv = function(delimiter) {
23859   var reFormat = new RegExp("[\"" + delimiter + "\n]"),
23860       delimiterCode = delimiter.charCodeAt(0);
23861
23862   function parse(text, f) {
23863     var convert, columns, rows = parseRows(text, function(row, i) {
23864       if (convert) return convert(row, i - 1);
23865       columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
23866     });
23867     rows.columns = columns;
23868     return rows;
23869   }
23870
23871   function parseRows(text, f) {
23872     var EOL = {}, // sentinel value for end-of-line
23873         EOF = {}, // sentinel value for end-of-file
23874         rows = [], // output rows
23875         N = text.length,
23876         I = 0, // current character index
23877         n = 0, // the current line number
23878         t, // the current token
23879         eol; // is the current token followed by EOL?
23880
23881     function token() {
23882       if (I >= N) return EOF; // special case: end of file
23883       if (eol) return eol = false, EOL; // special case: end of line
23884
23885       // special case: quotes
23886       var j = I, c;
23887       if (text.charCodeAt(j) === 34) {
23888         var i = j;
23889         while (i++ < N) {
23890           if (text.charCodeAt(i) === 34) {
23891             if (text.charCodeAt(i + 1) !== 34) break;
23892             ++i;
23893           }
23894         }
23895         I = i + 2;
23896         c = text.charCodeAt(i + 1);
23897         if (c === 13) {
23898           eol = true;
23899           if (text.charCodeAt(i + 2) === 10) ++I;
23900         } else if (c === 10) {
23901           eol = true;
23902         }
23903         return text.slice(j + 1, i).replace(/""/g, "\"");
23904       }
23905
23906       // common case: find next delimiter or newline
23907       while (I < N) {
23908         var k = 1;
23909         c = text.charCodeAt(I++);
23910         if (c === 10) eol = true; // \n
23911         else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
23912         else if (c !== delimiterCode) continue;
23913         return text.slice(j, I - k);
23914       }
23915
23916       // special case: last token before EOF
23917       return text.slice(j);
23918     }
23919
23920     while ((t = token()) !== EOF) {
23921       var a = [];
23922       while (t !== EOL && t !== EOF) {
23923         a.push(t);
23924         t = token();
23925       }
23926       if (f && (a = f(a, n++)) == null) continue;
23927       rows.push(a);
23928     }
23929
23930     return rows;
23931   }
23932
23933   function format(rows, columns) {
23934     if (columns == null) columns = inferColumns(rows);
23935     return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
23936       return columns.map(function(column) {
23937         return formatValue(row[column]);
23938       }).join(delimiter);
23939     })).join("\n");
23940   }
23941
23942   function formatRows(rows) {
23943     return rows.map(formatRow).join("\n");
23944   }
23945
23946   function formatRow(row) {
23947     return row.map(formatValue).join(delimiter);
23948   }
23949
23950   function formatValue(text) {
23951     return text == null ? ""
23952         : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
23953         : text;
23954   }
23955
23956   return {
23957     parse: parse,
23958     parseRows: parseRows,
23959     format: format,
23960     formatRows: formatRows
23961   };
23962 };
23963
23964 var csv = dsv(",");
23965
23966 var csvParse = csv.parse;
23967 var csvParseRows = csv.parseRows;
23968 var csvFormat = csv.format;
23969 var csvFormatRows = csv.formatRows;
23970
23971 var tsv = dsv("\t");
23972
23973 var tsvParse = tsv.parse;
23974 var tsvParseRows = tsv.parseRows;
23975 var tsvFormat = tsv.format;
23976 var tsvFormatRows = tsv.formatRows;
23977
23978 var request = function(url, callback) {
23979   var request,
23980       event = dispatch("beforesend", "progress", "load", "error"),
23981       mimeType,
23982       headers = map$1(),
23983       xhr = new XMLHttpRequest,
23984       user = null,
23985       password = null,
23986       response,
23987       responseType,
23988       timeout = 0;
23989
23990   // If IE does not support CORS, use XDomainRequest.
23991   if (typeof XDomainRequest !== "undefined"
23992       && !("withCredentials" in xhr)
23993       && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
23994
23995   "onload" in xhr
23996       ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
23997       : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
23998
23999   function respond(o) {
24000     var status = xhr.status, result;
24001     if (!status && hasResponse(xhr)
24002         || status >= 200 && status < 300
24003         || status === 304) {
24004       if (response) {
24005         try {
24006           result = response.call(request, xhr);
24007         } catch (e) {
24008           event.call("error", request, e);
24009           return;
24010         }
24011       } else {
24012         result = xhr;
24013       }
24014       event.call("load", request, result);
24015     } else {
24016       event.call("error", request, o);
24017     }
24018   }
24019
24020   xhr.onprogress = function(e) {
24021     event.call("progress", request, e);
24022   };
24023
24024   request = {
24025     header: function(name, value) {
24026       name = (name + "").toLowerCase();
24027       if (arguments.length < 2) return headers.get(name);
24028       if (value == null) headers.remove(name);
24029       else headers.set(name, value + "");
24030       return request;
24031     },
24032
24033     // If mimeType is non-null and no Accept header is set, a default is used.
24034     mimeType: function(value) {
24035       if (!arguments.length) return mimeType;
24036       mimeType = value == null ? null : value + "";
24037       return request;
24038     },
24039
24040     // Specifies what type the response value should take;
24041     // for instance, arraybuffer, blob, document, or text.
24042     responseType: function(value) {
24043       if (!arguments.length) return responseType;
24044       responseType = value;
24045       return request;
24046     },
24047
24048     timeout: function(value) {
24049       if (!arguments.length) return timeout;
24050       timeout = +value;
24051       return request;
24052     },
24053
24054     user: function(value) {
24055       return arguments.length < 1 ? user : (user = value == null ? null : value + "", request);
24056     },
24057
24058     password: function(value) {
24059       return arguments.length < 1 ? password : (password = value == null ? null : value + "", request);
24060     },
24061
24062     // Specify how to convert the response content to a specific type;
24063     // changes the callback value on "load" events.
24064     response: function(value) {
24065       response = value;
24066       return request;
24067     },
24068
24069     // Alias for send("GET", …).
24070     get: function(data, callback) {
24071       return request.send("GET", data, callback);
24072     },
24073
24074     // Alias for send("POST", …).
24075     post: function(data, callback) {
24076       return request.send("POST", data, callback);
24077     },
24078
24079     // If callback is non-null, it will be used for error and load events.
24080     send: function(method, data, callback) {
24081       xhr.open(method, url, true, user, password);
24082       if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
24083       if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
24084       if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
24085       if (responseType != null) xhr.responseType = responseType;
24086       if (timeout > 0) xhr.timeout = timeout;
24087       if (callback == null && typeof data === "function") callback = data, data = null;
24088       if (callback != null && callback.length === 1) callback = fixCallback(callback);
24089       if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
24090       event.call("beforesend", request, xhr);
24091       xhr.send(data == null ? null : data);
24092       return request;
24093     },
24094
24095     abort: function() {
24096       xhr.abort();
24097       return request;
24098     },
24099
24100     on: function() {
24101       var value = event.on.apply(event, arguments);
24102       return value === event ? request : value;
24103     }
24104   };
24105
24106   if (callback != null) {
24107     if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
24108     return request.get(callback);
24109   }
24110
24111   return request;
24112 };
24113
24114 function fixCallback(callback) {
24115   return function(error, xhr) {
24116     callback(error == null ? xhr : null);
24117   };
24118 }
24119
24120 function hasResponse(xhr) {
24121   var type = xhr.responseType;
24122   return type && type !== "text"
24123       ? xhr.response // null on error
24124       : xhr.responseText; // "" on error
24125 }
24126
24127 var type$2 = function(defaultMimeType, response) {
24128   return function(url, callback) {
24129     var r = request(url).mimeType(defaultMimeType).response(response);
24130     if (callback != null) {
24131       if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
24132       return r.get(callback);
24133     }
24134     return r;
24135   };
24136 };
24137
24138 var html = type$2("text/html", function(xhr) {
24139   return document.createRange().createContextualFragment(xhr.responseText);
24140 });
24141
24142 var json = type$2("application/json", function(xhr) {
24143   return JSON.parse(xhr.responseText);
24144 });
24145
24146 var text = type$2("text/plain", function(xhr) {
24147   return xhr.responseText;
24148 });
24149
24150 var xml = type$2("application/xml", function(xhr) {
24151   var xml = xhr.responseXML;
24152   if (!xml) throw new Error("parse error");
24153   return xml;
24154 });
24155
24156 var dsv$1 = function(defaultMimeType, parse) {
24157   return function(url, row, callback) {
24158     if (arguments.length < 3) callback = row, row = null;
24159     var r = request(url).mimeType(defaultMimeType);
24160     r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; };
24161     r.row(row);
24162     return callback ? r.get(callback) : r;
24163   };
24164 };
24165
24166 function responseOf(parse, row) {
24167   return function(request$$1) {
24168     return parse(request$$1.responseText, row);
24169   };
24170 }
24171
24172 var csv$1 = dsv$1("text/csv", csvParse);
24173
24174 var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
24175
24176 var frame = 0;
24177 var timeout = 0;
24178 var interval = 0;
24179 var pokeDelay = 1000;
24180 var taskHead;
24181 var taskTail;
24182 var clockLast = 0;
24183 var clockNow = 0;
24184 var clockSkew = 0;
24185 var clock = typeof performance === "object" && performance.now ? performance : Date;
24186 var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
24187
24188 function now() {
24189   return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
24190 }
24191
24192 function clearNow() {
24193   clockNow = 0;
24194 }
24195
24196 function Timer() {
24197   this._call =
24198   this._time =
24199   this._next = null;
24200 }
24201
24202 Timer.prototype = timer.prototype = {
24203   constructor: Timer,
24204   restart: function(callback, delay, time) {
24205     if (typeof callback !== "function") throw new TypeError("callback is not a function");
24206     time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
24207     if (!this._next && taskTail !== this) {
24208       if (taskTail) taskTail._next = this;
24209       else taskHead = this;
24210       taskTail = this;
24211     }
24212     this._call = callback;
24213     this._time = time;
24214     sleep();
24215   },
24216   stop: function() {
24217     if (this._call) {
24218       this._call = null;
24219       this._time = Infinity;
24220       sleep();
24221     }
24222   }
24223 };
24224
24225 function timer(callback, delay, time) {
24226   var t = new Timer;
24227   t.restart(callback, delay, time);
24228   return t;
24229 }
24230
24231 function timerFlush() {
24232   now(); // Get the current time, if not already set.
24233   ++frame; // Pretend we’ve set an alarm, if we haven’t already.
24234   var t = taskHead, e;
24235   while (t) {
24236     if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
24237     t = t._next;
24238   }
24239   --frame;
24240 }
24241
24242 function wake() {
24243   clockNow = (clockLast = clock.now()) + clockSkew;
24244   frame = timeout = 0;
24245   try {
24246     timerFlush();
24247   } finally {
24248     frame = 0;
24249     nap();
24250     clockNow = 0;
24251   }
24252 }
24253
24254 function poke$1() {
24255   var now = clock.now(), delay = now - clockLast;
24256   if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
24257 }
24258
24259 function nap() {
24260   var t0, t1 = taskHead, t2, time = Infinity;
24261   while (t1) {
24262     if (t1._call) {
24263       if (time > t1._time) time = t1._time;
24264       t0 = t1, t1 = t1._next;
24265     } else {
24266       t2 = t1._next, t1._next = null;
24267       t1 = t0 ? t0._next = t2 : taskHead = t2;
24268     }
24269   }
24270   taskTail = t0;
24271   sleep(time);
24272 }
24273
24274 function sleep(time) {
24275   if (frame) return; // Soonest alarm already set, or will be.
24276   if (timeout) timeout = clearTimeout(timeout);
24277   var delay = time - clockNow;
24278   if (delay > 24) {
24279     if (time < Infinity) timeout = setTimeout(wake, delay);
24280     if (interval) interval = clearInterval(interval);
24281   } else {
24282     if (!interval) interval = setInterval(poke$1, pokeDelay);
24283     frame = 1, setFrame(wake);
24284   }
24285 }
24286
24287 var timeout$1 = function(callback, delay, time) {
24288   var t = new Timer;
24289   delay = delay == null ? 0 : +delay;
24290   t.restart(function(elapsed) {
24291     t.stop();
24292     callback(elapsed + delay);
24293   }, delay, time);
24294   return t;
24295 };
24296
24297 var interval$1 = function(callback, delay, time) {
24298   var t = new Timer, total = delay;
24299   if (delay == null) return t.restart(callback, delay, time), t;
24300   delay = +delay, time = time == null ? now() : +time;
24301   t.restart(function tick(elapsed) {
24302     elapsed += total;
24303     t.restart(tick, total += delay, time);
24304     callback(elapsed);
24305   }, delay, time);
24306   return t;
24307 };
24308
24309 var t0$1 = new Date;
24310 var t1$1 = new Date;
24311
24312 function newInterval(floori, offseti, count, field) {
24313
24314   function interval(date) {
24315     return floori(date = new Date(+date)), date;
24316   }
24317
24318   interval.floor = interval;
24319
24320   interval.ceil = function(date) {
24321     return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
24322   };
24323
24324   interval.round = function(date) {
24325     var d0 = interval(date),
24326         d1 = interval.ceil(date);
24327     return date - d0 < d1 - date ? d0 : d1;
24328   };
24329
24330   interval.offset = function(date, step) {
24331     return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
24332   };
24333
24334   interval.range = function(start, stop, step) {
24335     var range = [];
24336     start = interval.ceil(start);
24337     step = step == null ? 1 : Math.floor(step);
24338     if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
24339     do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop)
24340     return range;
24341   };
24342
24343   interval.filter = function(test) {
24344     return newInterval(function(date) {
24345       if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
24346     }, function(date, step) {
24347       if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty
24348     });
24349   };
24350
24351   if (count) {
24352     interval.count = function(start, end) {
24353       t0$1.setTime(+start), t1$1.setTime(+end);
24354       floori(t0$1), floori(t1$1);
24355       return Math.floor(count(t0$1, t1$1));
24356     };
24357
24358     interval.every = function(step) {
24359       step = Math.floor(step);
24360       return !isFinite(step) || !(step > 0) ? null
24361           : !(step > 1) ? interval
24362           : interval.filter(field
24363               ? function(d) { return field(d) % step === 0; }
24364               : function(d) { return interval.count(0, d) % step === 0; });
24365     };
24366   }
24367
24368   return interval;
24369 }
24370
24371 var millisecond = newInterval(function() {
24372   // noop
24373 }, function(date, step) {
24374   date.setTime(+date + step);
24375 }, function(start, end) {
24376   return end - start;
24377 });
24378
24379 // An optimized implementation for this simple case.
24380 millisecond.every = function(k) {
24381   k = Math.floor(k);
24382   if (!isFinite(k) || !(k > 0)) return null;
24383   if (!(k > 1)) return millisecond;
24384   return newInterval(function(date) {
24385     date.setTime(Math.floor(date / k) * k);
24386   }, function(date, step) {
24387     date.setTime(+date + step * k);
24388   }, function(start, end) {
24389     return (end - start) / k;
24390   });
24391 };
24392
24393 var milliseconds = millisecond.range;
24394
24395 var durationSecond = 1e3;
24396 var durationMinute = 6e4;
24397 var durationHour = 36e5;
24398 var durationDay = 864e5;
24399 var durationWeek = 6048e5;
24400
24401 var second = newInterval(function(date) {
24402   date.setTime(Math.floor(date / durationSecond) * durationSecond);
24403 }, function(date, step) {
24404   date.setTime(+date + step * durationSecond);
24405 }, function(start, end) {
24406   return (end - start) / durationSecond;
24407 }, function(date) {
24408   return date.getUTCSeconds();
24409 });
24410
24411 var seconds = second.range;
24412
24413 var minute = newInterval(function(date) {
24414   date.setTime(Math.floor(date / durationMinute) * durationMinute);
24415 }, function(date, step) {
24416   date.setTime(+date + step * durationMinute);
24417 }, function(start, end) {
24418   return (end - start) / durationMinute;
24419 }, function(date) {
24420   return date.getMinutes();
24421 });
24422
24423 var minutes = minute.range;
24424
24425 var hour = newInterval(function(date) {
24426   var offset = date.getTimezoneOffset() * durationMinute % durationHour;
24427   if (offset < 0) offset += durationHour;
24428   date.setTime(Math.floor((+date - offset) / durationHour) * durationHour + offset);
24429 }, function(date, step) {
24430   date.setTime(+date + step * durationHour);
24431 }, function(start, end) {
24432   return (end - start) / durationHour;
24433 }, function(date) {
24434   return date.getHours();
24435 });
24436
24437 var hours = hour.range;
24438
24439 var day = newInterval(function(date) {
24440   date.setHours(0, 0, 0, 0);
24441 }, function(date, step) {
24442   date.setDate(date.getDate() + step);
24443 }, function(start, end) {
24444   return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay;
24445 }, function(date) {
24446   return date.getDate() - 1;
24447 });
24448
24449 var days = day.range;
24450
24451 function weekday(i) {
24452   return newInterval(function(date) {
24453     date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
24454     date.setHours(0, 0, 0, 0);
24455   }, function(date, step) {
24456     date.setDate(date.getDate() + step * 7);
24457   }, function(start, end) {
24458     return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek;
24459   });
24460 }
24461
24462 var sunday = weekday(0);
24463 var monday = weekday(1);
24464 var tuesday = weekday(2);
24465 var wednesday = weekday(3);
24466 var thursday = weekday(4);
24467 var friday = weekday(5);
24468 var saturday = weekday(6);
24469
24470 var sundays = sunday.range;
24471 var mondays = monday.range;
24472 var tuesdays = tuesday.range;
24473 var wednesdays = wednesday.range;
24474 var thursdays = thursday.range;
24475 var fridays = friday.range;
24476 var saturdays = saturday.range;
24477
24478 var month = newInterval(function(date) {
24479   date.setDate(1);
24480   date.setHours(0, 0, 0, 0);
24481 }, function(date, step) {
24482   date.setMonth(date.getMonth() + step);
24483 }, function(start, end) {
24484   return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
24485 }, function(date) {
24486   return date.getMonth();
24487 });
24488
24489 var months = month.range;
24490
24491 var year = newInterval(function(date) {
24492   date.setMonth(0, 1);
24493   date.setHours(0, 0, 0, 0);
24494 }, function(date, step) {
24495   date.setFullYear(date.getFullYear() + step);
24496 }, function(start, end) {
24497   return end.getFullYear() - start.getFullYear();
24498 }, function(date) {
24499   return date.getFullYear();
24500 });
24501
24502 // An optimized implementation for this simple case.
24503 year.every = function(k) {
24504   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
24505     date.setFullYear(Math.floor(date.getFullYear() / k) * k);
24506     date.setMonth(0, 1);
24507     date.setHours(0, 0, 0, 0);
24508   }, function(date, step) {
24509     date.setFullYear(date.getFullYear() + step * k);
24510   });
24511 };
24512
24513 var years = year.range;
24514
24515 var utcMinute = newInterval(function(date) {
24516   date.setUTCSeconds(0, 0);
24517 }, function(date, step) {
24518   date.setTime(+date + step * durationMinute);
24519 }, function(start, end) {
24520   return (end - start) / durationMinute;
24521 }, function(date) {
24522   return date.getUTCMinutes();
24523 });
24524
24525 var utcMinutes = utcMinute.range;
24526
24527 var utcHour = newInterval(function(date) {
24528   date.setUTCMinutes(0, 0, 0);
24529 }, function(date, step) {
24530   date.setTime(+date + step * durationHour);
24531 }, function(start, end) {
24532   return (end - start) / durationHour;
24533 }, function(date) {
24534   return date.getUTCHours();
24535 });
24536
24537 var utcHours = utcHour.range;
24538
24539 var utcDay = newInterval(function(date) {
24540   date.setUTCHours(0, 0, 0, 0);
24541 }, function(date, step) {
24542   date.setUTCDate(date.getUTCDate() + step);
24543 }, function(start, end) {
24544   return (end - start) / durationDay;
24545 }, function(date) {
24546   return date.getUTCDate() - 1;
24547 });
24548
24549 var utcDays = utcDay.range;
24550
24551 function utcWeekday(i) {
24552   return newInterval(function(date) {
24553     date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
24554     date.setUTCHours(0, 0, 0, 0);
24555   }, function(date, step) {
24556     date.setUTCDate(date.getUTCDate() + step * 7);
24557   }, function(start, end) {
24558     return (end - start) / durationWeek;
24559   });
24560 }
24561
24562 var utcSunday = utcWeekday(0);
24563 var utcMonday = utcWeekday(1);
24564 var utcTuesday = utcWeekday(2);
24565 var utcWednesday = utcWeekday(3);
24566 var utcThursday = utcWeekday(4);
24567 var utcFriday = utcWeekday(5);
24568 var utcSaturday = utcWeekday(6);
24569
24570 var utcSundays = utcSunday.range;
24571 var utcMondays = utcMonday.range;
24572 var utcTuesdays = utcTuesday.range;
24573 var utcWednesdays = utcWednesday.range;
24574 var utcThursdays = utcThursday.range;
24575 var utcFridays = utcFriday.range;
24576 var utcSaturdays = utcSaturday.range;
24577
24578 var utcMonth = newInterval(function(date) {
24579   date.setUTCDate(1);
24580   date.setUTCHours(0, 0, 0, 0);
24581 }, function(date, step) {
24582   date.setUTCMonth(date.getUTCMonth() + step);
24583 }, function(start, end) {
24584   return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
24585 }, function(date) {
24586   return date.getUTCMonth();
24587 });
24588
24589 var utcMonths = utcMonth.range;
24590
24591 var utcYear = newInterval(function(date) {
24592   date.setUTCMonth(0, 1);
24593   date.setUTCHours(0, 0, 0, 0);
24594 }, function(date, step) {
24595   date.setUTCFullYear(date.getUTCFullYear() + step);
24596 }, function(start, end) {
24597   return end.getUTCFullYear() - start.getUTCFullYear();
24598 }, function(date) {
24599   return date.getUTCFullYear();
24600 });
24601
24602 // An optimized implementation for this simple case.
24603 utcYear.every = function(k) {
24604   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
24605     date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
24606     date.setUTCMonth(0, 1);
24607     date.setUTCHours(0, 0, 0, 0);
24608   }, function(date, step) {
24609     date.setUTCFullYear(date.getUTCFullYear() + step * k);
24610   });
24611 };
24612
24613 var utcYears = utcYear.range;
24614
24615 // Computes the decimal coefficient and exponent of the specified number x with
24616 // significant digits p, where x is positive and p is in [1, 21] or undefined.
24617 // For example, formatDecimal(1.23) returns ["123", 0].
24618 var formatDecimal = function(x, p) {
24619   if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
24620   var i, coefficient = x.slice(0, i);
24621
24622   // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
24623   // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
24624   return [
24625     coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
24626     +x.slice(i + 1)
24627   ];
24628 };
24629
24630 var exponent$1 = function(x) {
24631   return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
24632 };
24633
24634 var formatGroup = function(grouping, thousands) {
24635   return function(value, width) {
24636     var i = value.length,
24637         t = [],
24638         j = 0,
24639         g = grouping[0],
24640         length = 0;
24641
24642     while (i > 0 && g > 0) {
24643       if (length + g + 1 > width) g = Math.max(1, width - length);
24644       t.push(value.substring(i -= g, i + g));
24645       if ((length += g + 1) > width) break;
24646       g = grouping[j = (j + 1) % grouping.length];
24647     }
24648
24649     return t.reverse().join(thousands);
24650   };
24651 };
24652
24653 var formatDefault = function(x, p) {
24654   x = x.toPrecision(p);
24655
24656   out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
24657     switch (x[i]) {
24658       case ".": i0 = i1 = i; break;
24659       case "0": if (i0 === 0) i0 = i; i1 = i; break;
24660       case "e": break out;
24661       default: if (i0 > 0) i0 = 0; break;
24662     }
24663   }
24664
24665   return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
24666 };
24667
24668 var prefixExponent;
24669
24670 var formatPrefixAuto = function(x, p) {
24671   var d = formatDecimal(x, p);
24672   if (!d) return x + "";
24673   var coefficient = d[0],
24674       exponent = d[1],
24675       i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
24676       n = coefficient.length;
24677   return i === n ? coefficient
24678       : i > n ? coefficient + new Array(i - n + 1).join("0")
24679       : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
24680       : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
24681 };
24682
24683 var formatRounded = function(x, p) {
24684   var d = formatDecimal(x, p);
24685   if (!d) return x + "";
24686   var coefficient = d[0],
24687       exponent = d[1];
24688   return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
24689       : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
24690       : coefficient + new Array(exponent - coefficient.length + 2).join("0");
24691 };
24692
24693 var formatTypes = {
24694   "": formatDefault,
24695   "%": function(x, p) { return (x * 100).toFixed(p); },
24696   "b": function(x) { return Math.round(x).toString(2); },
24697   "c": function(x) { return x + ""; },
24698   "d": function(x) { return Math.round(x).toString(10); },
24699   "e": function(x, p) { return x.toExponential(p); },
24700   "f": function(x, p) { return x.toFixed(p); },
24701   "g": function(x, p) { return x.toPrecision(p); },
24702   "o": function(x) { return Math.round(x).toString(8); },
24703   "p": function(x, p) { return formatRounded(x * 100, p); },
24704   "r": formatRounded,
24705   "s": formatPrefixAuto,
24706   "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
24707   "x": function(x) { return Math.round(x).toString(16); }
24708 };
24709
24710 // [[fill]align][sign][symbol][0][width][,][.precision][type]
24711 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
24712
24713 var formatSpecifier = function(specifier) {
24714   return new FormatSpecifier(specifier);
24715 };
24716
24717 function FormatSpecifier(specifier) {
24718   if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
24719
24720   var match,
24721       fill = match[1] || " ",
24722       align = match[2] || ">",
24723       sign = match[3] || "-",
24724       symbol = match[4] || "",
24725       zero = !!match[5],
24726       width = match[6] && +match[6],
24727       comma = !!match[7],
24728       precision = match[8] && +match[8].slice(1),
24729       type = match[9] || "";
24730
24731   // The "n" type is an alias for ",g".
24732   if (type === "n") comma = true, type = "g";
24733
24734   // Map invalid types to the default format.
24735   else if (!formatTypes[type]) type = "";
24736
24737   // If zero fill is specified, padding goes after sign and before digits.
24738   if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
24739
24740   this.fill = fill;
24741   this.align = align;
24742   this.sign = sign;
24743   this.symbol = symbol;
24744   this.zero = zero;
24745   this.width = width;
24746   this.comma = comma;
24747   this.precision = precision;
24748   this.type = type;
24749 }
24750
24751 FormatSpecifier.prototype.toString = function() {
24752   return this.fill
24753       + this.align
24754       + this.sign
24755       + this.symbol
24756       + (this.zero ? "0" : "")
24757       + (this.width == null ? "" : Math.max(1, this.width | 0))
24758       + (this.comma ? "," : "")
24759       + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
24760       + this.type;
24761 };
24762
24763 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
24764
24765 function identity$3(x) {
24766   return x;
24767 }
24768
24769 var formatLocale = function(locale) {
24770   var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
24771       currency = locale.currency,
24772       decimal = locale.decimal;
24773
24774   function newFormat(specifier) {
24775     specifier = formatSpecifier(specifier);
24776
24777     var fill = specifier.fill,
24778         align = specifier.align,
24779         sign = specifier.sign,
24780         symbol = specifier.symbol,
24781         zero = specifier.zero,
24782         width = specifier.width,
24783         comma = specifier.comma,
24784         precision = specifier.precision,
24785         type = specifier.type;
24786
24787     // Compute the prefix and suffix.
24788     // For SI-prefix, the suffix is lazily computed.
24789     var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
24790         suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
24791
24792     // What format function should we use?
24793     // Is this an integer type?
24794     // Can this type generate exponential notation?
24795     var formatType = formatTypes[type],
24796         maybeSuffix = !type || /[defgprs%]/.test(type);
24797
24798     // Set the default precision if not specified,
24799     // or clamp the specified precision to the supported range.
24800     // For significant precision, it must be in [1, 21].
24801     // For fixed precision, it must be in [0, 20].
24802     precision = precision == null ? (type ? 6 : 12)
24803         : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
24804         : Math.max(0, Math.min(20, precision));
24805
24806     function format(value) {
24807       var valuePrefix = prefix,
24808           valueSuffix = suffix,
24809           i, n, c;
24810
24811       if (type === "c") {
24812         valueSuffix = formatType(value) + valueSuffix;
24813         value = "";
24814       } else {
24815         value = +value;
24816
24817         // Convert negative to positive, and compute the prefix.
24818         // Note that -0 is not less than 0, but 1 / -0 is!
24819         var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
24820
24821         // Perform the initial formatting.
24822         value = formatType(value, precision);
24823
24824         // If the original value was negative, it may be rounded to zero during
24825         // formatting; treat this as (positive) zero.
24826         if (valueNegative) {
24827           i = -1, n = value.length;
24828           valueNegative = false;
24829           while (++i < n) {
24830             if (c = value.charCodeAt(i), (48 < c && c < 58)
24831                 || (type === "x" && 96 < c && c < 103)
24832                 || (type === "X" && 64 < c && c < 71)) {
24833               valueNegative = true;
24834               break;
24835             }
24836           }
24837         }
24838
24839         // Compute the prefix and suffix.
24840         valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
24841         valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
24842
24843         // Break the formatted value into the integer “value” part that can be
24844         // grouped, and fractional or exponential “suffix” part that is not.
24845         if (maybeSuffix) {
24846           i = -1, n = value.length;
24847           while (++i < n) {
24848             if (c = value.charCodeAt(i), 48 > c || c > 57) {
24849               valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
24850               value = value.slice(0, i);
24851               break;
24852             }
24853           }
24854         }
24855       }
24856
24857       // If the fill character is not "0", grouping is applied before padding.
24858       if (comma && !zero) value = group(value, Infinity);
24859
24860       // Compute the padding.
24861       var length = valuePrefix.length + value.length + valueSuffix.length,
24862           padding = length < width ? new Array(width - length + 1).join(fill) : "";
24863
24864       // If the fill character is "0", grouping is applied after padding.
24865       if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
24866
24867       // Reconstruct the final output based on the desired alignment.
24868       switch (align) {
24869         case "<": return valuePrefix + value + valueSuffix + padding;
24870         case "=": return valuePrefix + padding + value + valueSuffix;
24871         case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
24872       }
24873       return padding + valuePrefix + value + valueSuffix;
24874     }
24875
24876     format.toString = function() {
24877       return specifier + "";
24878     };
24879
24880     return format;
24881   }
24882
24883   function formatPrefix(specifier, value) {
24884     var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
24885         e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
24886         k = Math.pow(10, -e),
24887         prefix = prefixes[8 + e / 3];
24888     return function(value) {
24889       return f(k * value) + prefix;
24890     };
24891   }
24892
24893   return {
24894     format: newFormat,
24895     formatPrefix: formatPrefix
24896   };
24897 };
24898
24899 var locale$1;
24900 var format;
24901 var formatPrefix;
24902
24903 defaultLocale({
24904   decimal: ".",
24905   thousands: ",",
24906   grouping: [3],
24907   currency: ["$", ""]
24908 });
24909
24910 function defaultLocale(definition) {
24911   locale$1 = formatLocale(definition);
24912   format = locale$1.format;
24913   formatPrefix = locale$1.formatPrefix;
24914   return locale$1;
24915 }
24916
24917 var precisionFixed = function(step) {
24918   return Math.max(0, -exponent$1(Math.abs(step)));
24919 };
24920
24921 var precisionPrefix = function(step, value) {
24922   return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
24923 };
24924
24925 var precisionRound = function(step, max) {
24926   step = Math.abs(step), max = Math.abs(max) - step;
24927   return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
24928 };
24929
24930 function localDate(d) {
24931   if (0 <= d.y && d.y < 100) {
24932     var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
24933     date.setFullYear(d.y);
24934     return date;
24935   }
24936   return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
24937 }
24938
24939 function utcDate(d) {
24940   if (0 <= d.y && d.y < 100) {
24941     var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
24942     date.setUTCFullYear(d.y);
24943     return date;
24944   }
24945   return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
24946 }
24947
24948 function newYear(y) {
24949   return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
24950 }
24951
24952 function formatLocale$1(locale) {
24953   var locale_dateTime = locale.dateTime,
24954       locale_date = locale.date,
24955       locale_time = locale.time,
24956       locale_periods = locale.periods,
24957       locale_weekdays = locale.days,
24958       locale_shortWeekdays = locale.shortDays,
24959       locale_months = locale.months,
24960       locale_shortMonths = locale.shortMonths;
24961
24962   var periodRe = formatRe(locale_periods),
24963       periodLookup = formatLookup(locale_periods),
24964       weekdayRe = formatRe(locale_weekdays),
24965       weekdayLookup = formatLookup(locale_weekdays),
24966       shortWeekdayRe = formatRe(locale_shortWeekdays),
24967       shortWeekdayLookup = formatLookup(locale_shortWeekdays),
24968       monthRe = formatRe(locale_months),
24969       monthLookup = formatLookup(locale_months),
24970       shortMonthRe = formatRe(locale_shortMonths),
24971       shortMonthLookup = formatLookup(locale_shortMonths);
24972
24973   var formats = {
24974     "a": formatShortWeekday,
24975     "A": formatWeekday,
24976     "b": formatShortMonth,
24977     "B": formatMonth,
24978     "c": null,
24979     "d": formatDayOfMonth,
24980     "e": formatDayOfMonth,
24981     "H": formatHour24,
24982     "I": formatHour12,
24983     "j": formatDayOfYear,
24984     "L": formatMilliseconds,
24985     "m": formatMonthNumber,
24986     "M": formatMinutes,
24987     "p": formatPeriod,
24988     "S": formatSeconds,
24989     "U": formatWeekNumberSunday,
24990     "w": formatWeekdayNumber,
24991     "W": formatWeekNumberMonday,
24992     "x": null,
24993     "X": null,
24994     "y": formatYear,
24995     "Y": formatFullYear,
24996     "Z": formatZone,
24997     "%": formatLiteralPercent
24998   };
24999
25000   var utcFormats = {
25001     "a": formatUTCShortWeekday,
25002     "A": formatUTCWeekday,
25003     "b": formatUTCShortMonth,
25004     "B": formatUTCMonth,
25005     "c": null,
25006     "d": formatUTCDayOfMonth,
25007     "e": formatUTCDayOfMonth,
25008     "H": formatUTCHour24,
25009     "I": formatUTCHour12,
25010     "j": formatUTCDayOfYear,
25011     "L": formatUTCMilliseconds,
25012     "m": formatUTCMonthNumber,
25013     "M": formatUTCMinutes,
25014     "p": formatUTCPeriod,
25015     "S": formatUTCSeconds,
25016     "U": formatUTCWeekNumberSunday,
25017     "w": formatUTCWeekdayNumber,
25018     "W": formatUTCWeekNumberMonday,
25019     "x": null,
25020     "X": null,
25021     "y": formatUTCYear,
25022     "Y": formatUTCFullYear,
25023     "Z": formatUTCZone,
25024     "%": formatLiteralPercent
25025   };
25026
25027   var parses = {
25028     "a": parseShortWeekday,
25029     "A": parseWeekday,
25030     "b": parseShortMonth,
25031     "B": parseMonth,
25032     "c": parseLocaleDateTime,
25033     "d": parseDayOfMonth,
25034     "e": parseDayOfMonth,
25035     "H": parseHour24,
25036     "I": parseHour24,
25037     "j": parseDayOfYear,
25038     "L": parseMilliseconds,
25039     "m": parseMonthNumber,
25040     "M": parseMinutes,
25041     "p": parsePeriod,
25042     "S": parseSeconds,
25043     "U": parseWeekNumberSunday,
25044     "w": parseWeekdayNumber,
25045     "W": parseWeekNumberMonday,
25046     "x": parseLocaleDate,
25047     "X": parseLocaleTime,
25048     "y": parseYear,
25049     "Y": parseFullYear,
25050     "Z": parseZone,
25051     "%": parseLiteralPercent
25052   };
25053
25054   // These recursive directive definitions must be deferred.
25055   formats.x = newFormat(locale_date, formats);
25056   formats.X = newFormat(locale_time, formats);
25057   formats.c = newFormat(locale_dateTime, formats);
25058   utcFormats.x = newFormat(locale_date, utcFormats);
25059   utcFormats.X = newFormat(locale_time, utcFormats);
25060   utcFormats.c = newFormat(locale_dateTime, utcFormats);
25061
25062   function newFormat(specifier, formats) {
25063     return function(date) {
25064       var string = [],
25065           i = -1,
25066           j = 0,
25067           n = specifier.length,
25068           c,
25069           pad,
25070           format;
25071
25072       if (!(date instanceof Date)) date = new Date(+date);
25073
25074       while (++i < n) {
25075         if (specifier.charCodeAt(i) === 37) {
25076           string.push(specifier.slice(j, i));
25077           if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
25078           else pad = c === "e" ? " " : "0";
25079           if (format = formats[c]) c = format(date, pad);
25080           string.push(c);
25081           j = i + 1;
25082         }
25083       }
25084
25085       string.push(specifier.slice(j, i));
25086       return string.join("");
25087     };
25088   }
25089
25090   function newParse(specifier, newDate) {
25091     return function(string) {
25092       var d = newYear(1900),
25093           i = parseSpecifier(d, specifier, string += "", 0);
25094       if (i != string.length) return null;
25095
25096       // The am-pm flag is 0 for AM, and 1 for PM.
25097       if ("p" in d) d.H = d.H % 12 + d.p * 12;
25098
25099       // Convert day-of-week and week-of-year to day-of-year.
25100       if ("W" in d || "U" in d) {
25101         if (!("w" in d)) d.w = "W" in d ? 1 : 0;
25102         var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
25103         d.m = 0;
25104         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;
25105       }
25106
25107       // If a time zone is specified, all fields are interpreted as UTC and then
25108       // offset according to the specified time zone.
25109       if ("Z" in d) {
25110         d.H += d.Z / 100 | 0;
25111         d.M += d.Z % 100;
25112         return utcDate(d);
25113       }
25114
25115       // Otherwise, all fields are in local time.
25116       return newDate(d);
25117     };
25118   }
25119
25120   function parseSpecifier(d, specifier, string, j) {
25121     var i = 0,
25122         n = specifier.length,
25123         m = string.length,
25124         c,
25125         parse;
25126
25127     while (i < n) {
25128       if (j >= m) return -1;
25129       c = specifier.charCodeAt(i++);
25130       if (c === 37) {
25131         c = specifier.charAt(i++);
25132         parse = parses[c in pads ? specifier.charAt(i++) : c];
25133         if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
25134       } else if (c != string.charCodeAt(j++)) {
25135         return -1;
25136       }
25137     }
25138
25139     return j;
25140   }
25141
25142   function parsePeriod(d, string, i) {
25143     var n = periodRe.exec(string.slice(i));
25144     return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25145   }
25146
25147   function parseShortWeekday(d, string, i) {
25148     var n = shortWeekdayRe.exec(string.slice(i));
25149     return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25150   }
25151
25152   function parseWeekday(d, string, i) {
25153     var n = weekdayRe.exec(string.slice(i));
25154     return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25155   }
25156
25157   function parseShortMonth(d, string, i) {
25158     var n = shortMonthRe.exec(string.slice(i));
25159     return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25160   }
25161
25162   function parseMonth(d, string, i) {
25163     var n = monthRe.exec(string.slice(i));
25164     return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25165   }
25166
25167   function parseLocaleDateTime(d, string, i) {
25168     return parseSpecifier(d, locale_dateTime, string, i);
25169   }
25170
25171   function parseLocaleDate(d, string, i) {
25172     return parseSpecifier(d, locale_date, string, i);
25173   }
25174
25175   function parseLocaleTime(d, string, i) {
25176     return parseSpecifier(d, locale_time, string, i);
25177   }
25178
25179   function formatShortWeekday(d) {
25180     return locale_shortWeekdays[d.getDay()];
25181   }
25182
25183   function formatWeekday(d) {
25184     return locale_weekdays[d.getDay()];
25185   }
25186
25187   function formatShortMonth(d) {
25188     return locale_shortMonths[d.getMonth()];
25189   }
25190
25191   function formatMonth(d) {
25192     return locale_months[d.getMonth()];
25193   }
25194
25195   function formatPeriod(d) {
25196     return locale_periods[+(d.getHours() >= 12)];
25197   }
25198
25199   function formatUTCShortWeekday(d) {
25200     return locale_shortWeekdays[d.getUTCDay()];
25201   }
25202
25203   function formatUTCWeekday(d) {
25204     return locale_weekdays[d.getUTCDay()];
25205   }
25206
25207   function formatUTCShortMonth(d) {
25208     return locale_shortMonths[d.getUTCMonth()];
25209   }
25210
25211   function formatUTCMonth(d) {
25212     return locale_months[d.getUTCMonth()];
25213   }
25214
25215   function formatUTCPeriod(d) {
25216     return locale_periods[+(d.getUTCHours() >= 12)];
25217   }
25218
25219   return {
25220     format: function(specifier) {
25221       var f = newFormat(specifier += "", formats);
25222       f.toString = function() { return specifier; };
25223       return f;
25224     },
25225     parse: function(specifier) {
25226       var p = newParse(specifier += "", localDate);
25227       p.toString = function() { return specifier; };
25228       return p;
25229     },
25230     utcFormat: function(specifier) {
25231       var f = newFormat(specifier += "", utcFormats);
25232       f.toString = function() { return specifier; };
25233       return f;
25234     },
25235     utcParse: function(specifier) {
25236       var p = newParse(specifier, utcDate);
25237       p.toString = function() { return specifier; };
25238       return p;
25239     }
25240   };
25241 }
25242
25243 var pads = {"-": "", "_": " ", "0": "0"};
25244 var numberRe = /^\s*\d+/;
25245 var percentRe = /^%/;
25246 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
25247
25248 function pad(value, fill, width) {
25249   var sign = value < 0 ? "-" : "",
25250       string = (sign ? -value : value) + "",
25251       length = string.length;
25252   return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
25253 }
25254
25255 function requote(s) {
25256   return s.replace(requoteRe, "\\$&");
25257 }
25258
25259 function formatRe(names) {
25260   return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
25261 }
25262
25263 function formatLookup(names) {
25264   var map = {}, i = -1, n = names.length;
25265   while (++i < n) map[names[i].toLowerCase()] = i;
25266   return map;
25267 }
25268
25269 function parseWeekdayNumber(d, string, i) {
25270   var n = numberRe.exec(string.slice(i, i + 1));
25271   return n ? (d.w = +n[0], i + n[0].length) : -1;
25272 }
25273
25274 function parseWeekNumberSunday(d, string, i) {
25275   var n = numberRe.exec(string.slice(i));
25276   return n ? (d.U = +n[0], i + n[0].length) : -1;
25277 }
25278
25279 function parseWeekNumberMonday(d, string, i) {
25280   var n = numberRe.exec(string.slice(i));
25281   return n ? (d.W = +n[0], i + n[0].length) : -1;
25282 }
25283
25284 function parseFullYear(d, string, i) {
25285   var n = numberRe.exec(string.slice(i, i + 4));
25286   return n ? (d.y = +n[0], i + n[0].length) : -1;
25287 }
25288
25289 function parseYear(d, string, i) {
25290   var n = numberRe.exec(string.slice(i, i + 2));
25291   return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
25292 }
25293
25294 function parseZone(d, string, i) {
25295   var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
25296   return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
25297 }
25298
25299 function parseMonthNumber(d, string, i) {
25300   var n = numberRe.exec(string.slice(i, i + 2));
25301   return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
25302 }
25303
25304 function parseDayOfMonth(d, string, i) {
25305   var n = numberRe.exec(string.slice(i, i + 2));
25306   return n ? (d.d = +n[0], i + n[0].length) : -1;
25307 }
25308
25309 function parseDayOfYear(d, string, i) {
25310   var n = numberRe.exec(string.slice(i, i + 3));
25311   return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
25312 }
25313
25314 function parseHour24(d, string, i) {
25315   var n = numberRe.exec(string.slice(i, i + 2));
25316   return n ? (d.H = +n[0], i + n[0].length) : -1;
25317 }
25318
25319 function parseMinutes(d, string, i) {
25320   var n = numberRe.exec(string.slice(i, i + 2));
25321   return n ? (d.M = +n[0], i + n[0].length) : -1;
25322 }
25323
25324 function parseSeconds(d, string, i) {
25325   var n = numberRe.exec(string.slice(i, i + 2));
25326   return n ? (d.S = +n[0], i + n[0].length) : -1;
25327 }
25328
25329 function parseMilliseconds(d, string, i) {
25330   var n = numberRe.exec(string.slice(i, i + 3));
25331   return n ? (d.L = +n[0], i + n[0].length) : -1;
25332 }
25333
25334 function parseLiteralPercent(d, string, i) {
25335   var n = percentRe.exec(string.slice(i, i + 1));
25336   return n ? i + n[0].length : -1;
25337 }
25338
25339 function formatDayOfMonth(d, p) {
25340   return pad(d.getDate(), p, 2);
25341 }
25342
25343 function formatHour24(d, p) {
25344   return pad(d.getHours(), p, 2);
25345 }
25346
25347 function formatHour12(d, p) {
25348   return pad(d.getHours() % 12 || 12, p, 2);
25349 }
25350
25351 function formatDayOfYear(d, p) {
25352   return pad(1 + day.count(year(d), d), p, 3);
25353 }
25354
25355 function formatMilliseconds(d, p) {
25356   return pad(d.getMilliseconds(), p, 3);
25357 }
25358
25359 function formatMonthNumber(d, p) {
25360   return pad(d.getMonth() + 1, p, 2);
25361 }
25362
25363 function formatMinutes(d, p) {
25364   return pad(d.getMinutes(), p, 2);
25365 }
25366
25367 function formatSeconds(d, p) {
25368   return pad(d.getSeconds(), p, 2);
25369 }
25370
25371 function formatWeekNumberSunday(d, p) {
25372   return pad(sunday.count(year(d), d), p, 2);
25373 }
25374
25375 function formatWeekdayNumber(d) {
25376   return d.getDay();
25377 }
25378
25379 function formatWeekNumberMonday(d, p) {
25380   return pad(monday.count(year(d), d), p, 2);
25381 }
25382
25383 function formatYear(d, p) {
25384   return pad(d.getFullYear() % 100, p, 2);
25385 }
25386
25387 function formatFullYear(d, p) {
25388   return pad(d.getFullYear() % 10000, p, 4);
25389 }
25390
25391 function formatZone(d) {
25392   var z = d.getTimezoneOffset();
25393   return (z > 0 ? "-" : (z *= -1, "+"))
25394       + pad(z / 60 | 0, "0", 2)
25395       + pad(z % 60, "0", 2);
25396 }
25397
25398 function formatUTCDayOfMonth(d, p) {
25399   return pad(d.getUTCDate(), p, 2);
25400 }
25401
25402 function formatUTCHour24(d, p) {
25403   return pad(d.getUTCHours(), p, 2);
25404 }
25405
25406 function formatUTCHour12(d, p) {
25407   return pad(d.getUTCHours() % 12 || 12, p, 2);
25408 }
25409
25410 function formatUTCDayOfYear(d, p) {
25411   return pad(1 + utcDay.count(utcYear(d), d), p, 3);
25412 }
25413
25414 function formatUTCMilliseconds(d, p) {
25415   return pad(d.getUTCMilliseconds(), p, 3);
25416 }
25417
25418 function formatUTCMonthNumber(d, p) {
25419   return pad(d.getUTCMonth() + 1, p, 2);
25420 }
25421
25422 function formatUTCMinutes(d, p) {
25423   return pad(d.getUTCMinutes(), p, 2);
25424 }
25425
25426 function formatUTCSeconds(d, p) {
25427   return pad(d.getUTCSeconds(), p, 2);
25428 }
25429
25430 function formatUTCWeekNumberSunday(d, p) {
25431   return pad(utcSunday.count(utcYear(d), d), p, 2);
25432 }
25433
25434 function formatUTCWeekdayNumber(d) {
25435   return d.getUTCDay();
25436 }
25437
25438 function formatUTCWeekNumberMonday(d, p) {
25439   return pad(utcMonday.count(utcYear(d), d), p, 2);
25440 }
25441
25442 function formatUTCYear(d, p) {
25443   return pad(d.getUTCFullYear() % 100, p, 2);
25444 }
25445
25446 function formatUTCFullYear(d, p) {
25447   return pad(d.getUTCFullYear() % 10000, p, 4);
25448 }
25449
25450 function formatUTCZone() {
25451   return "+0000";
25452 }
25453
25454 function formatLiteralPercent() {
25455   return "%";
25456 }
25457
25458 var locale$2;
25459 var timeFormat;
25460 var timeParse;
25461 var utcFormat;
25462 var utcParse;
25463
25464 defaultLocale$1({
25465   dateTime: "%x, %X",
25466   date: "%-m/%-d/%Y",
25467   time: "%-I:%M:%S %p",
25468   periods: ["AM", "PM"],
25469   days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
25470   shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
25471   months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
25472   shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
25473 });
25474
25475 function defaultLocale$1(definition) {
25476   locale$2 = formatLocale$1(definition);
25477   timeFormat = locale$2.format;
25478   timeParse = locale$2.parse;
25479   utcFormat = locale$2.utcFormat;
25480   utcParse = locale$2.utcParse;
25481   return locale$2;
25482 }
25483
25484 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
25485
25486 function formatIsoNative(date) {
25487   return date.toISOString();
25488 }
25489
25490 var formatIso = Date.prototype.toISOString
25491     ? formatIsoNative
25492     : utcFormat(isoSpecifier);
25493
25494 function parseIsoNative(string) {
25495   var date = new Date(string);
25496   return isNaN(date) ? null : date;
25497 }
25498
25499 var parseIso = +new Date("2000-01-01T00:00:00.000Z")
25500     ? parseIsoNative
25501     : utcParse(isoSpecifier);
25502
25503 var array$2 = Array.prototype;
25504
25505 var map$3 = array$2.map;
25506 var slice$3 = array$2.slice;
25507
25508 var implicit = {name: "implicit"};
25509
25510 function ordinal(range) {
25511   var index = map$1(),
25512       domain = [],
25513       unknown = implicit;
25514
25515   range = range == null ? [] : slice$3.call(range);
25516
25517   function scale(d) {
25518     var key = d + "", i = index.get(key);
25519     if (!i) {
25520       if (unknown !== implicit) return unknown;
25521       index.set(key, i = domain.push(d));
25522     }
25523     return range[(i - 1) % range.length];
25524   }
25525
25526   scale.domain = function(_) {
25527     if (!arguments.length) return domain.slice();
25528     domain = [], index = map$1();
25529     var i = -1, n = _.length, d, key;
25530     while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
25531     return scale;
25532   };
25533
25534   scale.range = function(_) {
25535     return arguments.length ? (range = slice$3.call(_), scale) : range.slice();
25536   };
25537
25538   scale.unknown = function(_) {
25539     return arguments.length ? (unknown = _, scale) : unknown;
25540   };
25541
25542   scale.copy = function() {
25543     return ordinal()
25544         .domain(domain)
25545         .range(range)
25546         .unknown(unknown);
25547   };
25548
25549   return scale;
25550 }
25551
25552 function band() {
25553   var scale = ordinal().unknown(undefined),
25554       domain = scale.domain,
25555       ordinalRange = scale.range,
25556       range$$1 = [0, 1],
25557       step,
25558       bandwidth,
25559       round = false,
25560       paddingInner = 0,
25561       paddingOuter = 0,
25562       align = 0.5;
25563
25564   delete scale.unknown;
25565
25566   function rescale() {
25567     var n = domain().length,
25568         reverse = range$$1[1] < range$$1[0],
25569         start = range$$1[reverse - 0],
25570         stop = range$$1[1 - reverse];
25571     step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
25572     if (round) step = Math.floor(step);
25573     start += (stop - start - step * (n - paddingInner)) * align;
25574     bandwidth = step * (1 - paddingInner);
25575     if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
25576     var values = range(n).map(function(i) { return start + step * i; });
25577     return ordinalRange(reverse ? values.reverse() : values);
25578   }
25579
25580   scale.domain = function(_) {
25581     return arguments.length ? (domain(_), rescale()) : domain();
25582   };
25583
25584   scale.range = function(_) {
25585     return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice();
25586   };
25587
25588   scale.rangeRound = function(_) {
25589     return range$$1 = [+_[0], +_[1]], round = true, rescale();
25590   };
25591
25592   scale.bandwidth = function() {
25593     return bandwidth;
25594   };
25595
25596   scale.step = function() {
25597     return step;
25598   };
25599
25600   scale.round = function(_) {
25601     return arguments.length ? (round = !!_, rescale()) : round;
25602   };
25603
25604   scale.padding = function(_) {
25605     return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
25606   };
25607
25608   scale.paddingInner = function(_) {
25609     return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
25610   };
25611
25612   scale.paddingOuter = function(_) {
25613     return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
25614   };
25615
25616   scale.align = function(_) {
25617     return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
25618   };
25619
25620   scale.copy = function() {
25621     return band()
25622         .domain(domain())
25623         .range(range$$1)
25624         .round(round)
25625         .paddingInner(paddingInner)
25626         .paddingOuter(paddingOuter)
25627         .align(align);
25628   };
25629
25630   return rescale();
25631 }
25632
25633 function pointish(scale) {
25634   var copy = scale.copy;
25635
25636   scale.padding = scale.paddingOuter;
25637   delete scale.paddingInner;
25638   delete scale.paddingOuter;
25639
25640   scale.copy = function() {
25641     return pointish(copy());
25642   };
25643
25644   return scale;
25645 }
25646
25647 function point$4() {
25648   return pointish(band().paddingInner(1));
25649 }
25650
25651 var constant$4 = function(x) {
25652   return function() {
25653     return x;
25654   };
25655 };
25656
25657 var number$1 = function(x) {
25658   return +x;
25659 };
25660
25661 var unit = [0, 1];
25662
25663 function deinterpolateLinear(a, b) {
25664   return (b -= (a = +a))
25665       ? function(x) { return (x - a) / b; }
25666       : constant$4(b);
25667 }
25668
25669 function deinterpolateClamp(deinterpolate) {
25670   return function(a, b) {
25671     var d = deinterpolate(a = +a, b = +b);
25672     return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
25673   };
25674 }
25675
25676 function reinterpolateClamp(reinterpolate) {
25677   return function(a, b) {
25678     var r = reinterpolate(a = +a, b = +b);
25679     return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
25680   };
25681 }
25682
25683 function bimap(domain, range$$1, deinterpolate, reinterpolate) {
25684   var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1];
25685   if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
25686   else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
25687   return function(x) { return r0(d0(x)); };
25688 }
25689
25690 function polymap(domain, range$$1, deinterpolate, reinterpolate) {
25691   var j = Math.min(domain.length, range$$1.length) - 1,
25692       d = new Array(j),
25693       r = new Array(j),
25694       i = -1;
25695
25696   // Reverse descending domains.
25697   if (domain[j] < domain[0]) {
25698     domain = domain.slice().reverse();
25699     range$$1 = range$$1.slice().reverse();
25700   }
25701
25702   while (++i < j) {
25703     d[i] = deinterpolate(domain[i], domain[i + 1]);
25704     r[i] = reinterpolate(range$$1[i], range$$1[i + 1]);
25705   }
25706
25707   return function(x) {
25708     var i = bisectRight(domain, x, 1, j) - 1;
25709     return r[i](d[i](x));
25710   };
25711 }
25712
25713 function copy(source, target) {
25714   return target
25715       .domain(source.domain())
25716       .range(source.range())
25717       .interpolate(source.interpolate())
25718       .clamp(source.clamp());
25719 }
25720
25721 // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
25722 // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
25723 function continuous(deinterpolate, reinterpolate) {
25724   var domain = unit,
25725       range$$1 = unit,
25726       interpolate$$1 = interpolate,
25727       clamp = false,
25728       piecewise,
25729       output,
25730       input;
25731
25732   function rescale() {
25733     piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap;
25734     output = input = null;
25735     return scale;
25736   }
25737
25738   function scale(x) {
25739     return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x);
25740   }
25741
25742   scale.invert = function(y) {
25743     return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
25744   };
25745
25746   scale.domain = function(_) {
25747     return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice();
25748   };
25749
25750   scale.range = function(_) {
25751     return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice();
25752   };
25753
25754   scale.rangeRound = function(_) {
25755     return range$$1 = slice$3.call(_), interpolate$$1 = interpolateRound, rescale();
25756   };
25757
25758   scale.clamp = function(_) {
25759     return arguments.length ? (clamp = !!_, rescale()) : clamp;
25760   };
25761
25762   scale.interpolate = function(_) {
25763     return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1;
25764   };
25765
25766   return rescale();
25767 }
25768
25769 var tickFormat = function(domain, count, specifier) {
25770   var start = domain[0],
25771       stop = domain[domain.length - 1],
25772       step = tickStep(start, stop, count == null ? 10 : count),
25773       precision;
25774   specifier = formatSpecifier(specifier == null ? ",f" : specifier);
25775   switch (specifier.type) {
25776     case "s": {
25777       var value = Math.max(Math.abs(start), Math.abs(stop));
25778       if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
25779       return formatPrefix(specifier, value);
25780     }
25781     case "":
25782     case "e":
25783     case "g":
25784     case "p":
25785     case "r": {
25786       if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
25787       break;
25788     }
25789     case "f":
25790     case "%": {
25791       if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
25792       break;
25793     }
25794   }
25795   return format(specifier);
25796 };
25797
25798 function linearish(scale) {
25799   var domain = scale.domain;
25800
25801   scale.ticks = function(count) {
25802     var d = domain();
25803     return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
25804   };
25805
25806   scale.tickFormat = function(count, specifier) {
25807     return tickFormat(domain(), count, specifier);
25808   };
25809
25810   scale.nice = function(count) {
25811     var d = domain(),
25812         i = d.length - 1,
25813         n = count == null ? 10 : count,
25814         start = d[0],
25815         stop = d[i],
25816         step = tickStep(start, stop, n);
25817
25818     if (step) {
25819       step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n);
25820       d[0] = Math.floor(start / step) * step;
25821       d[i] = Math.ceil(stop / step) * step;
25822       domain(d);
25823     }
25824
25825     return scale;
25826   };
25827
25828   return scale;
25829 }
25830
25831 function linear$2() {
25832   var scale = continuous(deinterpolateLinear, interpolateNumber);
25833
25834   scale.copy = function() {
25835     return copy(scale, linear$2());
25836   };
25837
25838   return linearish(scale);
25839 }
25840
25841 function identity$4() {
25842   var domain = [0, 1];
25843
25844   function scale(x) {
25845     return +x;
25846   }
25847
25848   scale.invert = scale;
25849
25850   scale.domain = scale.range = function(_) {
25851     return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice();
25852   };
25853
25854   scale.copy = function() {
25855     return identity$4().domain(domain);
25856   };
25857
25858   return linearish(scale);
25859 }
25860
25861 var nice = function(domain, interval) {
25862   domain = domain.slice();
25863
25864   var i0 = 0,
25865       i1 = domain.length - 1,
25866       x0 = domain[i0],
25867       x1 = domain[i1],
25868       t;
25869
25870   if (x1 < x0) {
25871     t = i0, i0 = i1, i1 = t;
25872     t = x0, x0 = x1, x1 = t;
25873   }
25874
25875   domain[i0] = interval.floor(x0);
25876   domain[i1] = interval.ceil(x1);
25877   return domain;
25878 };
25879
25880 function deinterpolate(a, b) {
25881   return (b = Math.log(b / a))
25882       ? function(x) { return Math.log(x / a) / b; }
25883       : constant$4(b);
25884 }
25885
25886 function reinterpolate(a, b) {
25887   return a < 0
25888       ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
25889       : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
25890 }
25891
25892 function pow10(x) {
25893   return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
25894 }
25895
25896 function powp(base) {
25897   return base === 10 ? pow10
25898       : base === Math.E ? Math.exp
25899       : function(x) { return Math.pow(base, x); };
25900 }
25901
25902 function logp(base) {
25903   return base === Math.E ? Math.log
25904       : base === 10 && Math.log10
25905       || base === 2 && Math.log2
25906       || (base = Math.log(base), function(x) { return Math.log(x) / base; });
25907 }
25908
25909 function reflect(f) {
25910   return function(x) {
25911     return -f(-x);
25912   };
25913 }
25914
25915 function log() {
25916   var scale = continuous(deinterpolate, reinterpolate).domain([1, 10]),
25917       domain = scale.domain,
25918       base = 10,
25919       logs = logp(10),
25920       pows = powp(10);
25921
25922   function rescale() {
25923     logs = logp(base), pows = powp(base);
25924     if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
25925     return scale;
25926   }
25927
25928   scale.base = function(_) {
25929     return arguments.length ? (base = +_, rescale()) : base;
25930   };
25931
25932   scale.domain = function(_) {
25933     return arguments.length ? (domain(_), rescale()) : domain();
25934   };
25935
25936   scale.ticks = function(count) {
25937     var d = domain(),
25938         u = d[0],
25939         v = d[d.length - 1],
25940         r;
25941
25942     if (r = v < u) i = u, u = v, v = i;
25943
25944     var i = logs(u),
25945         j = logs(v),
25946         p,
25947         k,
25948         t,
25949         n = count == null ? 10 : +count,
25950         z = [];
25951
25952     if (!(base % 1) && j - i < n) {
25953       i = Math.round(i) - 1, j = Math.round(j) + 1;
25954       if (u > 0) for (; i < j; ++i) {
25955         for (k = 1, p = pows(i); k < base; ++k) {
25956           t = p * k;
25957           if (t < u) continue;
25958           if (t > v) break;
25959           z.push(t);
25960         }
25961       } else for (; i < j; ++i) {
25962         for (k = base - 1, p = pows(i); k >= 1; --k) {
25963           t = p * k;
25964           if (t < u) continue;
25965           if (t > v) break;
25966           z.push(t);
25967         }
25968       }
25969     } else {
25970       z = ticks(i, j, Math.min(j - i, n)).map(pows);
25971     }
25972
25973     return r ? z.reverse() : z;
25974   };
25975
25976   scale.tickFormat = function(count, specifier) {
25977     if (specifier == null) specifier = base === 10 ? ".0e" : ",";
25978     if (typeof specifier !== "function") specifier = format(specifier);
25979     if (count === Infinity) return specifier;
25980     if (count == null) count = 10;
25981     var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
25982     return function(d) {
25983       var i = d / pows(Math.round(logs(d)));
25984       if (i * base < base - 0.5) i *= base;
25985       return i <= k ? specifier(d) : "";
25986     };
25987   };
25988
25989   scale.nice = function() {
25990     return domain(nice(domain(), {
25991       floor: function(x) { return pows(Math.floor(logs(x))); },
25992       ceil: function(x) { return pows(Math.ceil(logs(x))); }
25993     }));
25994   };
25995
25996   scale.copy = function() {
25997     return copy(scale, log().base(base));
25998   };
25999
26000   return scale;
26001 }
26002
26003 function raise(x, exponent) {
26004   return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
26005 }
26006
26007 function pow() {
26008   var exponent = 1,
26009       scale = continuous(deinterpolate, reinterpolate),
26010       domain = scale.domain;
26011
26012   function deinterpolate(a, b) {
26013     return (b = raise(b, exponent) - (a = raise(a, exponent)))
26014         ? function(x) { return (raise(x, exponent) - a) / b; }
26015         : constant$4(b);
26016   }
26017
26018   function reinterpolate(a, b) {
26019     b = raise(b, exponent) - (a = raise(a, exponent));
26020     return function(t) { return raise(a + b * t, 1 / exponent); };
26021   }
26022
26023   scale.exponent = function(_) {
26024     return arguments.length ? (exponent = +_, domain(domain())) : exponent;
26025   };
26026
26027   scale.copy = function() {
26028     return copy(scale, pow().exponent(exponent));
26029   };
26030
26031   return linearish(scale);
26032 }
26033
26034 function sqrt() {
26035   return pow().exponent(0.5);
26036 }
26037
26038 function quantile$$1() {
26039   var domain = [],
26040       range$$1 = [],
26041       thresholds = [];
26042
26043   function rescale() {
26044     var i = 0, n = Math.max(1, range$$1.length);
26045     thresholds = new Array(n - 1);
26046     while (++i < n) thresholds[i - 1] = threshold(domain, i / n);
26047     return scale;
26048   }
26049
26050   function scale(x) {
26051     if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)];
26052   }
26053
26054   scale.invertExtent = function(y) {
26055     var i = range$$1.indexOf(y);
26056     return i < 0 ? [NaN, NaN] : [
26057       i > 0 ? thresholds[i - 1] : domain[0],
26058       i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
26059     ];
26060   };
26061
26062   scale.domain = function(_) {
26063     if (!arguments.length) return domain.slice();
26064     domain = [];
26065     for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
26066     domain.sort(ascending);
26067     return rescale();
26068   };
26069
26070   scale.range = function(_) {
26071     return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice();
26072   };
26073
26074   scale.quantiles = function() {
26075     return thresholds.slice();
26076   };
26077
26078   scale.copy = function() {
26079     return quantile$$1()
26080         .domain(domain)
26081         .range(range$$1);
26082   };
26083
26084   return scale;
26085 }
26086
26087 function quantize$1() {
26088   var x0 = 0,
26089       x1 = 1,
26090       n = 1,
26091       domain = [0.5],
26092       range$$1 = [0, 1];
26093
26094   function scale(x) {
26095     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
26096   }
26097
26098   function rescale() {
26099     var i = -1;
26100     domain = new Array(n);
26101     while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
26102     return scale;
26103   }
26104
26105   scale.domain = function(_) {
26106     return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
26107   };
26108
26109   scale.range = function(_) {
26110     return arguments.length ? (n = (range$$1 = slice$3.call(_)).length - 1, rescale()) : range$$1.slice();
26111   };
26112
26113   scale.invertExtent = function(y) {
26114     var i = range$$1.indexOf(y);
26115     return i < 0 ? [NaN, NaN]
26116         : i < 1 ? [x0, domain[0]]
26117         : i >= n ? [domain[n - 1], x1]
26118         : [domain[i - 1], domain[i]];
26119   };
26120
26121   scale.copy = function() {
26122     return quantize$1()
26123         .domain([x0, x1])
26124         .range(range$$1);
26125   };
26126
26127   return linearish(scale);
26128 }
26129
26130 function threshold$1() {
26131   var domain = [0.5],
26132       range$$1 = [0, 1],
26133       n = 1;
26134
26135   function scale(x) {
26136     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
26137   }
26138
26139   scale.domain = function(_) {
26140     return arguments.length ? (domain = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice();
26141   };
26142
26143   scale.range = function(_) {
26144     return arguments.length ? (range$$1 = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice();
26145   };
26146
26147   scale.invertExtent = function(y) {
26148     var i = range$$1.indexOf(y);
26149     return [domain[i - 1], domain[i]];
26150   };
26151
26152   scale.copy = function() {
26153     return threshold$1()
26154         .domain(domain)
26155         .range(range$$1);
26156   };
26157
26158   return scale;
26159 }
26160
26161 var durationSecond$1 = 1000;
26162 var durationMinute$1 = durationSecond$1 * 60;
26163 var durationHour$1 = durationMinute$1 * 60;
26164 var durationDay$1 = durationHour$1 * 24;
26165 var durationWeek$1 = durationDay$1 * 7;
26166 var durationMonth = durationDay$1 * 30;
26167 var durationYear = durationDay$1 * 365;
26168
26169 function date$1(t) {
26170   return new Date(t);
26171 }
26172
26173 function number$2(t) {
26174   return t instanceof Date ? +t : +new Date(+t);
26175 }
26176
26177 function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) {
26178   var scale = continuous(deinterpolateLinear, interpolateNumber),
26179       invert = scale.invert,
26180       domain = scale.domain;
26181
26182   var formatMillisecond = format(".%L"),
26183       formatSecond = format(":%S"),
26184       formatMinute = format("%I:%M"),
26185       formatHour = format("%I %p"),
26186       formatDay = format("%a %d"),
26187       formatWeek = format("%b %d"),
26188       formatMonth = format("%B"),
26189       formatYear = format("%Y");
26190
26191   var tickIntervals = [
26192     [second$$1,  1,      durationSecond$1],
26193     [second$$1,  5,  5 * durationSecond$1],
26194     [second$$1, 15, 15 * durationSecond$1],
26195     [second$$1, 30, 30 * durationSecond$1],
26196     [minute$$1,  1,      durationMinute$1],
26197     [minute$$1,  5,  5 * durationMinute$1],
26198     [minute$$1, 15, 15 * durationMinute$1],
26199     [minute$$1, 30, 30 * durationMinute$1],
26200     [  hour$$1,  1,      durationHour$1  ],
26201     [  hour$$1,  3,  3 * durationHour$1  ],
26202     [  hour$$1,  6,  6 * durationHour$1  ],
26203     [  hour$$1, 12, 12 * durationHour$1  ],
26204     [   day$$1,  1,      durationDay$1   ],
26205     [   day$$1,  2,  2 * durationDay$1   ],
26206     [  week,  1,      durationWeek$1  ],
26207     [ month$$1,  1,      durationMonth ],
26208     [ month$$1,  3,  3 * durationMonth ],
26209     [  year$$1,  1,      durationYear  ]
26210   ];
26211
26212   function tickFormat(date) {
26213     return (second$$1(date) < date ? formatMillisecond
26214         : minute$$1(date) < date ? formatSecond
26215         : hour$$1(date) < date ? formatMinute
26216         : day$$1(date) < date ? formatHour
26217         : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek)
26218         : year$$1(date) < date ? formatMonth
26219         : formatYear)(date);
26220   }
26221
26222   function tickInterval(interval, start, stop, step) {
26223     if (interval == null) interval = 10;
26224
26225     // If a desired tick count is specified, pick a reasonable tick interval
26226     // based on the extent of the domain and a rough estimate of tick size.
26227     // Otherwise, assume interval is already a time interval and use it.
26228     if (typeof interval === "number") {
26229       var target = Math.abs(stop - start) / interval,
26230           i = bisector(function(i) { return i[2]; }).right(tickIntervals, target);
26231       if (i === tickIntervals.length) {
26232         step = tickStep(start / durationYear, stop / durationYear, interval);
26233         interval = year$$1;
26234       } else if (i) {
26235         i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
26236         step = i[1];
26237         interval = i[0];
26238       } else {
26239         step = tickStep(start, stop, interval);
26240         interval = millisecond$$1;
26241       }
26242     }
26243
26244     return step == null ? interval : interval.every(step);
26245   }
26246
26247   scale.invert = function(y) {
26248     return new Date(invert(y));
26249   };
26250
26251   scale.domain = function(_) {
26252     return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1);
26253   };
26254
26255   scale.ticks = function(interval, step) {
26256     var d = domain(),
26257         t0 = d[0],
26258         t1 = d[d.length - 1],
26259         r = t1 < t0,
26260         t;
26261     if (r) t = t0, t0 = t1, t1 = t;
26262     t = tickInterval(interval, t0, t1, step);
26263     t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
26264     return r ? t.reverse() : t;
26265   };
26266
26267   scale.tickFormat = function(count, specifier) {
26268     return specifier == null ? tickFormat : format(specifier);
26269   };
26270
26271   scale.nice = function(interval, step) {
26272     var d = domain();
26273     return (interval = tickInterval(interval, d[0], d[d.length - 1], step))
26274         ? domain(nice(d, interval))
26275         : scale;
26276   };
26277
26278   scale.copy = function() {
26279     return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format));
26280   };
26281
26282   return scale;
26283 }
26284
26285 var time = function() {
26286   return calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
26287 };
26288
26289 var utcTime = function() {
26290   return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
26291 };
26292
26293 var colors = function(s) {
26294   return s.match(/.{6}/g).map(function(x) {
26295     return "#" + x;
26296   });
26297 };
26298
26299 var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
26300
26301 var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
26302
26303 var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
26304
26305 var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
26306
26307 var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0));
26308
26309 var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
26310
26311 var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
26312
26313 var rainbow = cubehelix();
26314
26315 var rainbow$1 = function(t) {
26316   if (t < 0 || t > 1) t -= Math.floor(t);
26317   var ts = Math.abs(t - 0.5);
26318   rainbow.h = 360 * t - 100;
26319   rainbow.s = 1.5 - 1.5 * ts;
26320   rainbow.l = 0.8 - 0.9 * ts;
26321   return rainbow + "";
26322 };
26323
26324 function ramp(range) {
26325   var n = range.length;
26326   return function(t) {
26327     return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
26328   };
26329 }
26330
26331 var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
26332
26333 var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf"));
26334
26335 var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4"));
26336
26337 var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
26338
26339 function sequential(interpolator) {
26340   var x0 = 0,
26341       x1 = 1,
26342       clamp = false;
26343
26344   function scale(x) {
26345     var t = (x - x0) / (x1 - x0);
26346     return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t);
26347   }
26348
26349   scale.domain = function(_) {
26350     return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
26351   };
26352
26353   scale.clamp = function(_) {
26354     return arguments.length ? (clamp = !!_, scale) : clamp;
26355   };
26356
26357   scale.interpolator = function(_) {
26358     return arguments.length ? (interpolator = _, scale) : interpolator;
26359   };
26360
26361   scale.copy = function() {
26362     return sequential(interpolator).domain([x0, x1]).clamp(clamp);
26363   };
26364
26365   return linearish(scale);
26366 }
26367
26368 var xhtml = "http://www.w3.org/1999/xhtml";
26369
26370 var namespaces = {
26371   svg: "http://www.w3.org/2000/svg",
26372   xhtml: xhtml,
26373   xlink: "http://www.w3.org/1999/xlink",
26374   xml: "http://www.w3.org/XML/1998/namespace",
26375   xmlns: "http://www.w3.org/2000/xmlns/"
26376 };
26377
26378 var namespace = function(name) {
26379   var prefix = name += "", i = prefix.indexOf(":");
26380   if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
26381   return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
26382 };
26383
26384 function creatorInherit(name) {
26385   return function() {
26386     var document = this.ownerDocument,
26387         uri = this.namespaceURI;
26388     return uri === xhtml && document.documentElement.namespaceURI === xhtml
26389         ? document.createElement(name)
26390         : document.createElementNS(uri, name);
26391   };
26392 }
26393
26394 function creatorFixed(fullname) {
26395   return function() {
26396     return this.ownerDocument.createElementNS(fullname.space, fullname.local);
26397   };
26398 }
26399
26400 var creator = function(name) {
26401   var fullname = namespace(name);
26402   return (fullname.local
26403       ? creatorFixed
26404       : creatorInherit)(fullname);
26405 };
26406
26407 var nextId = 0;
26408
26409 function local() {
26410   return new Local;
26411 }
26412
26413 function Local() {
26414   this._ = "@" + (++nextId).toString(36);
26415 }
26416
26417 Local.prototype = local.prototype = {
26418   constructor: Local,
26419   get: function(node) {
26420     var id = this._;
26421     while (!(id in node)) if (!(node = node.parentNode)) return;
26422     return node[id];
26423   },
26424   set: function(node, value) {
26425     return node[this._] = value;
26426   },
26427   remove: function(node) {
26428     return this._ in node && delete node[this._];
26429   },
26430   toString: function() {
26431     return this._;
26432   }
26433 };
26434
26435 var matcher = function(selector) {
26436   return function() {
26437     return this.matches(selector);
26438   };
26439 };
26440
26441 if (typeof document !== "undefined") {
26442   var element = document.documentElement;
26443   if (!element.matches) {
26444     var vendorMatches = element.webkitMatchesSelector
26445         || element.msMatchesSelector
26446         || element.mozMatchesSelector
26447         || element.oMatchesSelector;
26448     matcher = function(selector) {
26449       return function() {
26450         return vendorMatches.call(this, selector);
26451       };
26452     };
26453   }
26454 }
26455
26456 var matcher$1 = matcher;
26457
26458 var filterEvents = {};
26459
26460 var event = null;
26461
26462 if (typeof document !== "undefined") {
26463   var element$1 = document.documentElement;
26464   if (!("onmouseenter" in element$1)) {
26465     filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
26466   }
26467 }
26468
26469 function filterContextListener(listener, index, group) {
26470   listener = contextListener(listener, index, group);
26471   return function(event) {
26472     var related = event.relatedTarget;
26473     if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
26474       listener.call(this, event);
26475     }
26476   };
26477 }
26478
26479 function contextListener(listener, index, group) {
26480   return function(event1) {
26481     var event0 = event; // Events can be reentrant (e.g., focus).
26482     event = event1;
26483     try {
26484       listener.call(this, this.__data__, index, group);
26485     } finally {
26486       event = event0;
26487     }
26488   };
26489 }
26490
26491 function parseTypenames$1(typenames) {
26492   return typenames.trim().split(/^|\s+/).map(function(t) {
26493     var name = "", i = t.indexOf(".");
26494     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
26495     return {type: t, name: name};
26496   });
26497 }
26498
26499 function onRemove(typename) {
26500   return function() {
26501     var on = this.__on;
26502     if (!on) return;
26503     for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
26504       if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
26505         this.removeEventListener(o.type, o.listener, o.capture);
26506       } else {
26507         on[++i] = o;
26508       }
26509     }
26510     if (++i) on.length = i;
26511     else delete this.__on;
26512   };
26513 }
26514
26515 function onAdd(typename, value, capture) {
26516   var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
26517   return function(d, i, group) {
26518     var on = this.__on, o, listener = wrap(value, i, group);
26519     if (on) for (var j = 0, m = on.length; j < m; ++j) {
26520       if ((o = on[j]).type === typename.type && o.name === typename.name) {
26521         this.removeEventListener(o.type, o.listener, o.capture);
26522         this.addEventListener(o.type, o.listener = listener, o.capture = capture);
26523         o.value = value;
26524         return;
26525       }
26526     }
26527     this.addEventListener(typename.type, listener, capture);
26528     o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
26529     if (!on) this.__on = [o];
26530     else on.push(o);
26531   };
26532 }
26533
26534 var selection_on = function(typename, value, capture) {
26535   var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
26536
26537   if (arguments.length < 2) {
26538     var on = this.node().__on;
26539     if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
26540       for (i = 0, o = on[j]; i < n; ++i) {
26541         if ((t = typenames[i]).type === o.type && t.name === o.name) {
26542           return o.value;
26543         }
26544       }
26545     }
26546     return;
26547   }
26548
26549   on = value ? onAdd : onRemove;
26550   if (capture == null) capture = false;
26551   for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
26552   return this;
26553 };
26554
26555 function customEvent(event1, listener, that, args) {
26556   var event0 = event;
26557   event1.sourceEvent = event;
26558   event = event1;
26559   try {
26560     return listener.apply(that, args);
26561   } finally {
26562     event = event0;
26563   }
26564 }
26565
26566 var sourceEvent = function() {
26567   var current = event, source;
26568   while (source = current.sourceEvent) current = source;
26569   return current;
26570 };
26571
26572 var point$5 = function(node, event) {
26573   var svg = node.ownerSVGElement || node;
26574
26575   if (svg.createSVGPoint) {
26576     var point = svg.createSVGPoint();
26577     point.x = event.clientX, point.y = event.clientY;
26578     point = point.matrixTransform(node.getScreenCTM().inverse());
26579     return [point.x, point.y];
26580   }
26581
26582   var rect = node.getBoundingClientRect();
26583   return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
26584 };
26585
26586 var mouse = function(node) {
26587   var event = sourceEvent();
26588   if (event.changedTouches) event = event.changedTouches[0];
26589   return point$5(node, event);
26590 };
26591
26592 function none$2() {}
26593
26594 var selector = function(selector) {
26595   return selector == null ? none$2 : function() {
26596     return this.querySelector(selector);
26597   };
26598 };
26599
26600 var selection_select = function(select) {
26601   if (typeof select !== "function") select = selector(select);
26602
26603   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
26604     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
26605       if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
26606         if ("__data__" in node) subnode.__data__ = node.__data__;
26607         subgroup[i] = subnode;
26608       }
26609     }
26610   }
26611
26612   return new Selection(subgroups, this._parents);
26613 };
26614
26615 function empty() {
26616   return [];
26617 }
26618
26619 var selectorAll = function(selector) {
26620   return selector == null ? empty : function() {
26621     return this.querySelectorAll(selector);
26622   };
26623 };
26624
26625 var selection_selectAll = function(select) {
26626   if (typeof select !== "function") select = selectorAll(select);
26627
26628   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
26629     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
26630       if (node = group[i]) {
26631         subgroups.push(select.call(node, node.__data__, i, group));
26632         parents.push(node);
26633       }
26634     }
26635   }
26636
26637   return new Selection(subgroups, parents);
26638 };
26639
26640 var selection_filter = function(match) {
26641   if (typeof match !== "function") match = matcher$1(match);
26642
26643   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
26644     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
26645       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
26646         subgroup.push(node);
26647       }
26648     }
26649   }
26650
26651   return new Selection(subgroups, this._parents);
26652 };
26653
26654 var sparse = function(update) {
26655   return new Array(update.length);
26656 };
26657
26658 var selection_enter = function() {
26659   return new Selection(this._enter || this._groups.map(sparse), this._parents);
26660 };
26661
26662 function EnterNode(parent, datum) {
26663   this.ownerDocument = parent.ownerDocument;
26664   this.namespaceURI = parent.namespaceURI;
26665   this._next = null;
26666   this._parent = parent;
26667   this.__data__ = datum;
26668 }
26669
26670 EnterNode.prototype = {
26671   constructor: EnterNode,
26672   appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
26673   insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
26674   querySelector: function(selector) { return this._parent.querySelector(selector); },
26675   querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
26676 };
26677
26678 var constant$5 = function(x) {
26679   return function() {
26680     return x;
26681   };
26682 };
26683
26684 var keyPrefix = "$"; // Protect against keys like “__proto__”.
26685
26686 function bindIndex(parent, group, enter, update, exit, data) {
26687   var i = 0,
26688       node,
26689       groupLength = group.length,
26690       dataLength = data.length;
26691
26692   // Put any non-null nodes that fit into update.
26693   // Put any null nodes into enter.
26694   // Put any remaining data into enter.
26695   for (; i < dataLength; ++i) {
26696     if (node = group[i]) {
26697       node.__data__ = data[i];
26698       update[i] = node;
26699     } else {
26700       enter[i] = new EnterNode(parent, data[i]);
26701     }
26702   }
26703
26704   // Put any non-null nodes that don’t fit into exit.
26705   for (; i < groupLength; ++i) {
26706     if (node = group[i]) {
26707       exit[i] = node;
26708     }
26709   }
26710 }
26711
26712 function bindKey(parent, group, enter, update, exit, data, key) {
26713   var i,
26714       node,
26715       nodeByKeyValue = {},
26716       groupLength = group.length,
26717       dataLength = data.length,
26718       keyValues = new Array(groupLength),
26719       keyValue;
26720
26721   // Compute the key for each node.
26722   // If multiple nodes have the same key, the duplicates are added to exit.
26723   for (i = 0; i < groupLength; ++i) {
26724     if (node = group[i]) {
26725       keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
26726       if (keyValue in nodeByKeyValue) {
26727         exit[i] = node;
26728       } else {
26729         nodeByKeyValue[keyValue] = node;
26730       }
26731     }
26732   }
26733
26734   // Compute the key for each datum.
26735   // If there a node associated with this key, join and add it to update.
26736   // If there is not (or the key is a duplicate), add it to enter.
26737   for (i = 0; i < dataLength; ++i) {
26738     keyValue = keyPrefix + key.call(parent, data[i], i, data);
26739     if (node = nodeByKeyValue[keyValue]) {
26740       update[i] = node;
26741       node.__data__ = data[i];
26742       nodeByKeyValue[keyValue] = null;
26743     } else {
26744       enter[i] = new EnterNode(parent, data[i]);
26745     }
26746   }
26747
26748   // Add any remaining nodes that were not bound to data to exit.
26749   for (i = 0; i < groupLength; ++i) {
26750     if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
26751       exit[i] = node;
26752     }
26753   }
26754 }
26755
26756 var selection_data = function(value, key) {
26757   if (!value) {
26758     data = new Array(this.size()), j = -1;
26759     this.each(function(d) { data[++j] = d; });
26760     return data;
26761   }
26762
26763   var bind = key ? bindKey : bindIndex,
26764       parents = this._parents,
26765       groups = this._groups;
26766
26767   if (typeof value !== "function") value = constant$5(value);
26768
26769   for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
26770     var parent = parents[j],
26771         group = groups[j],
26772         groupLength = group.length,
26773         data = value.call(parent, parent && parent.__data__, j, parents),
26774         dataLength = data.length,
26775         enterGroup = enter[j] = new Array(dataLength),
26776         updateGroup = update[j] = new Array(dataLength),
26777         exitGroup = exit[j] = new Array(groupLength);
26778
26779     bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
26780
26781     // Now connect the enter nodes to their following update node, such that
26782     // appendChild can insert the materialized enter node before this node,
26783     // rather than at the end of the parent node.
26784     for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
26785       if (previous = enterGroup[i0]) {
26786         if (i0 >= i1) i1 = i0 + 1;
26787         while (!(next = updateGroup[i1]) && ++i1 < dataLength);
26788         previous._next = next || null;
26789       }
26790     }
26791   }
26792
26793   update = new Selection(update, parents);
26794   update._enter = enter;
26795   update._exit = exit;
26796   return update;
26797 };
26798
26799 var selection_exit = function() {
26800   return new Selection(this._exit || this._groups.map(sparse), this._parents);
26801 };
26802
26803 var selection_merge = function(selection) {
26804
26805   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) {
26806     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
26807       if (node = group0[i] || group1[i]) {
26808         merge[i] = node;
26809       }
26810     }
26811   }
26812
26813   for (; j < m0; ++j) {
26814     merges[j] = groups0[j];
26815   }
26816
26817   return new Selection(merges, this._parents);
26818 };
26819
26820 var selection_order = function() {
26821
26822   for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
26823     for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
26824       if (node = group[i]) {
26825         if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
26826         next = node;
26827       }
26828     }
26829   }
26830
26831   return this;
26832 };
26833
26834 var selection_sort = function(compare) {
26835   if (!compare) compare = ascending$2;
26836
26837   function compareNode(a, b) {
26838     return a && b ? compare(a.__data__, b.__data__) : !a - !b;
26839   }
26840
26841   for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
26842     for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
26843       if (node = group[i]) {
26844         sortgroup[i] = node;
26845       }
26846     }
26847     sortgroup.sort(compareNode);
26848   }
26849
26850   return new Selection(sortgroups, this._parents).order();
26851 };
26852
26853 function ascending$2(a, b) {
26854   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
26855 }
26856
26857 var selection_call = function() {
26858   var callback = arguments[0];
26859   arguments[0] = this;
26860   callback.apply(null, arguments);
26861   return this;
26862 };
26863
26864 var selection_nodes = function() {
26865   var nodes = new Array(this.size()), i = -1;
26866   this.each(function() { nodes[++i] = this; });
26867   return nodes;
26868 };
26869
26870 var selection_node = function() {
26871
26872   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
26873     for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
26874       var node = group[i];
26875       if (node) return node;
26876     }
26877   }
26878
26879   return null;
26880 };
26881
26882 var selection_size = function() {
26883   var size = 0;
26884   this.each(function() { ++size; });
26885   return size;
26886 };
26887
26888 var selection_empty = function() {
26889   return !this.node();
26890 };
26891
26892 var selection_each = function(callback) {
26893
26894   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
26895     for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
26896       if (node = group[i]) callback.call(node, node.__data__, i, group);
26897     }
26898   }
26899
26900   return this;
26901 };
26902
26903 function attrRemove(name) {
26904   return function() {
26905     this.removeAttribute(name);
26906   };
26907 }
26908
26909 function attrRemoveNS(fullname) {
26910   return function() {
26911     this.removeAttributeNS(fullname.space, fullname.local);
26912   };
26913 }
26914
26915 function attrConstant(name, value) {
26916   return function() {
26917     this.setAttribute(name, value);
26918   };
26919 }
26920
26921 function attrConstantNS(fullname, value) {
26922   return function() {
26923     this.setAttributeNS(fullname.space, fullname.local, value);
26924   };
26925 }
26926
26927 function attrFunction(name, value) {
26928   return function() {
26929     var v = value.apply(this, arguments);
26930     if (v == null) this.removeAttribute(name);
26931     else this.setAttribute(name, v);
26932   };
26933 }
26934
26935 function attrFunctionNS(fullname, value) {
26936   return function() {
26937     var v = value.apply(this, arguments);
26938     if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
26939     else this.setAttributeNS(fullname.space, fullname.local, v);
26940   };
26941 }
26942
26943 var selection_attr = function(name, value) {
26944   var fullname = namespace(name);
26945
26946   if (arguments.length < 2) {
26947     var node = this.node();
26948     return fullname.local
26949         ? node.getAttributeNS(fullname.space, fullname.local)
26950         : node.getAttribute(fullname);
26951   }
26952
26953   return this.each((value == null
26954       ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
26955       ? (fullname.local ? attrFunctionNS : attrFunction)
26956       : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
26957 };
26958
26959 var window$1 = function(node) {
26960   return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
26961       || (node.document && node) // node is a Window
26962       || node.defaultView; // node is a Document
26963 };
26964
26965 function styleRemove(name) {
26966   return function() {
26967     this.style.removeProperty(name);
26968   };
26969 }
26970
26971 function styleConstant(name, value, priority) {
26972   return function() {
26973     this.style.setProperty(name, value, priority);
26974   };
26975 }
26976
26977 function styleFunction(name, value, priority) {
26978   return function() {
26979     var v = value.apply(this, arguments);
26980     if (v == null) this.style.removeProperty(name);
26981     else this.style.setProperty(name, v, priority);
26982   };
26983 }
26984
26985 var selection_style = function(name, value, priority) {
26986   var node;
26987   return arguments.length > 1
26988       ? this.each((value == null
26989             ? styleRemove : typeof value === "function"
26990             ? styleFunction
26991             : styleConstant)(name, value, priority == null ? "" : priority))
26992       : window$1(node = this.node())
26993           .getComputedStyle(node, null)
26994           .getPropertyValue(name);
26995 };
26996
26997 function propertyRemove(name) {
26998   return function() {
26999     delete this[name];
27000   };
27001 }
27002
27003 function propertyConstant(name, value) {
27004   return function() {
27005     this[name] = value;
27006   };
27007 }
27008
27009 function propertyFunction(name, value) {
27010   return function() {
27011     var v = value.apply(this, arguments);
27012     if (v == null) delete this[name];
27013     else this[name] = v;
27014   };
27015 }
27016
27017 var selection_property = function(name, value) {
27018   return arguments.length > 1
27019       ? this.each((value == null
27020           ? propertyRemove : typeof value === "function"
27021           ? propertyFunction
27022           : propertyConstant)(name, value))
27023       : this.node()[name];
27024 };
27025
27026 function classArray(string) {
27027   return string.trim().split(/^|\s+/);
27028 }
27029
27030 function classList(node) {
27031   return node.classList || new ClassList(node);
27032 }
27033
27034 function ClassList(node) {
27035   this._node = node;
27036   this._names = classArray(node.getAttribute("class") || "");
27037 }
27038
27039 ClassList.prototype = {
27040   add: function(name) {
27041     var i = this._names.indexOf(name);
27042     if (i < 0) {
27043       this._names.push(name);
27044       this._node.setAttribute("class", this._names.join(" "));
27045     }
27046   },
27047   remove: function(name) {
27048     var i = this._names.indexOf(name);
27049     if (i >= 0) {
27050       this._names.splice(i, 1);
27051       this._node.setAttribute("class", this._names.join(" "));
27052     }
27053   },
27054   contains: function(name) {
27055     return this._names.indexOf(name) >= 0;
27056   }
27057 };
27058
27059 function classedAdd(node, names) {
27060   var list = classList(node), i = -1, n = names.length;
27061   while (++i < n) list.add(names[i]);
27062 }
27063
27064 function classedRemove(node, names) {
27065   var list = classList(node), i = -1, n = names.length;
27066   while (++i < n) list.remove(names[i]);
27067 }
27068
27069 function classedTrue(names) {
27070   return function() {
27071     classedAdd(this, names);
27072   };
27073 }
27074
27075 function classedFalse(names) {
27076   return function() {
27077     classedRemove(this, names);
27078   };
27079 }
27080
27081 function classedFunction(names, value) {
27082   return function() {
27083     (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
27084   };
27085 }
27086
27087 var selection_classed = function(name, value) {
27088   var names = classArray(name + "");
27089
27090   if (arguments.length < 2) {
27091     var list = classList(this.node()), i = -1, n = names.length;
27092     while (++i < n) if (!list.contains(names[i])) return false;
27093     return true;
27094   }
27095
27096   return this.each((typeof value === "function"
27097       ? classedFunction : value
27098       ? classedTrue
27099       : classedFalse)(names, value));
27100 };
27101
27102 function textRemove() {
27103   this.textContent = "";
27104 }
27105
27106 function textConstant(value) {
27107   return function() {
27108     this.textContent = value;
27109   };
27110 }
27111
27112 function textFunction(value) {
27113   return function() {
27114     var v = value.apply(this, arguments);
27115     this.textContent = v == null ? "" : v;
27116   };
27117 }
27118
27119 var selection_text = function(value) {
27120   return arguments.length
27121       ? this.each(value == null
27122           ? textRemove : (typeof value === "function"
27123           ? textFunction
27124           : textConstant)(value))
27125       : this.node().textContent;
27126 };
27127
27128 function htmlRemove() {
27129   this.innerHTML = "";
27130 }
27131
27132 function htmlConstant(value) {
27133   return function() {
27134     this.innerHTML = value;
27135   };
27136 }
27137
27138 function htmlFunction(value) {
27139   return function() {
27140     var v = value.apply(this, arguments);
27141     this.innerHTML = v == null ? "" : v;
27142   };
27143 }
27144
27145 var selection_html = function(value) {
27146   return arguments.length
27147       ? this.each(value == null
27148           ? htmlRemove : (typeof value === "function"
27149           ? htmlFunction
27150           : htmlConstant)(value))
27151       : this.node().innerHTML;
27152 };
27153
27154 function raise$1() {
27155   if (this.nextSibling) this.parentNode.appendChild(this);
27156 }
27157
27158 var selection_raise = function() {
27159   return this.each(raise$1);
27160 };
27161
27162 function lower() {
27163   if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
27164 }
27165
27166 var selection_lower = function() {
27167   return this.each(lower);
27168 };
27169
27170 var selection_append = function(name) {
27171   var create = typeof name === "function" ? name : creator(name);
27172   return this.select(function() {
27173     return this.appendChild(create.apply(this, arguments));
27174   });
27175 };
27176
27177 function constantNull() {
27178   return null;
27179 }
27180
27181 var selection_insert = function(name, before) {
27182   var create = typeof name === "function" ? name : creator(name),
27183       select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
27184   return this.select(function() {
27185     return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
27186   });
27187 };
27188
27189 function remove() {
27190   var parent = this.parentNode;
27191   if (parent) parent.removeChild(this);
27192 }
27193
27194 var selection_remove = function() {
27195   return this.each(remove);
27196 };
27197
27198 var selection_datum = function(value) {
27199   return arguments.length
27200       ? this.property("__data__", value)
27201       : this.node().__data__;
27202 };
27203
27204 function dispatchEvent(node, type, params) {
27205   var window = window$1(node),
27206       event = window.CustomEvent;
27207
27208   if (event) {
27209     event = new event(type, params);
27210   } else {
27211     event = window.document.createEvent("Event");
27212     if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
27213     else event.initEvent(type, false, false);
27214   }
27215
27216   node.dispatchEvent(event);
27217 }
27218
27219 function dispatchConstant(type, params) {
27220   return function() {
27221     return dispatchEvent(this, type, params);
27222   };
27223 }
27224
27225 function dispatchFunction(type, params) {
27226   return function() {
27227     return dispatchEvent(this, type, params.apply(this, arguments));
27228   };
27229 }
27230
27231 var selection_dispatch = function(type, params) {
27232   return this.each((typeof params === "function"
27233       ? dispatchFunction
27234       : dispatchConstant)(type, params));
27235 };
27236
27237 var root = [null];
27238
27239 function Selection(groups, parents) {
27240   this._groups = groups;
27241   this._parents = parents;
27242 }
27243
27244 function selection() {
27245   return new Selection([[document.documentElement]], root);
27246 }
27247
27248 Selection.prototype = selection.prototype = {
27249   constructor: Selection,
27250   select: selection_select,
27251   selectAll: selection_selectAll,
27252   filter: selection_filter,
27253   data: selection_data,
27254   enter: selection_enter,
27255   exit: selection_exit,
27256   merge: selection_merge,
27257   order: selection_order,
27258   sort: selection_sort,
27259   call: selection_call,
27260   nodes: selection_nodes,
27261   node: selection_node,
27262   size: selection_size,
27263   empty: selection_empty,
27264   each: selection_each,
27265   attr: selection_attr,
27266   style: selection_style,
27267   property: selection_property,
27268   classed: selection_classed,
27269   text: selection_text,
27270   html: selection_html,
27271   raise: selection_raise,
27272   lower: selection_lower,
27273   append: selection_append,
27274   insert: selection_insert,
27275   remove: selection_remove,
27276   datum: selection_datum,
27277   on: selection_on,
27278   dispatch: selection_dispatch
27279 };
27280
27281 var select = function(selector) {
27282   return typeof selector === "string"
27283       ? new Selection([[document.querySelector(selector)]], [document.documentElement])
27284       : new Selection([[selector]], root);
27285 };
27286
27287 var selectAll = function(selector) {
27288   return typeof selector === "string"
27289       ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
27290       : new Selection([selector == null ? [] : selector], root);
27291 };
27292
27293 var touch = function(node, touches, identifier) {
27294   if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
27295
27296   for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
27297     if ((touch = touches[i]).identifier === identifier) {
27298       return point$5(node, touch);
27299     }
27300   }
27301
27302   return null;
27303 };
27304
27305 var touches = function(node, touches) {
27306   if (touches == null) touches = sourceEvent().touches;
27307
27308   for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
27309     points[i] = point$5(node, touches[i]);
27310   }
27311
27312   return points;
27313 };
27314
27315 var emptyOn = dispatch("start", "end", "interrupt");
27316 var emptyTween = [];
27317
27318 var CREATED = 0;
27319 var SCHEDULED = 1;
27320 var STARTING = 2;
27321 var STARTED = 3;
27322 var RUNNING = 4;
27323 var ENDING = 5;
27324 var ENDED = 6;
27325
27326 var schedule = function(node, name, id, index, group, timing) {
27327   var schedules = node.__transition;
27328   if (!schedules) node.__transition = {};
27329   else if (id in schedules) return;
27330   create(node, id, {
27331     name: name,
27332     index: index, // For context during callback.
27333     group: group, // For context during callback.
27334     on: emptyOn,
27335     tween: emptyTween,
27336     time: timing.time,
27337     delay: timing.delay,
27338     duration: timing.duration,
27339     ease: timing.ease,
27340     timer: null,
27341     state: CREATED
27342   });
27343 };
27344
27345 function init(node, id) {
27346   var schedule = node.__transition;
27347   if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late");
27348   return schedule;
27349 }
27350
27351 function set$3(node, id) {
27352   var schedule = node.__transition;
27353   if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late");
27354   return schedule;
27355 }
27356
27357 function get$1(node, id) {
27358   var schedule = node.__transition;
27359   if (!schedule || !(schedule = schedule[id])) throw new Error("too late");
27360   return schedule;
27361 }
27362
27363 function create(node, id, self) {
27364   var schedules = node.__transition,
27365       tween;
27366
27367   // Initialize the self timer when the transition is created.
27368   // Note the actual delay is not known until the first callback!
27369   schedules[id] = self;
27370   self.timer = timer(schedule, 0, self.time);
27371
27372   function schedule(elapsed) {
27373     self.state = SCHEDULED;
27374     self.timer.restart(start, self.delay, self.time);
27375
27376     // If the elapsed delay is less than our first sleep, start immediately.
27377     if (self.delay <= elapsed) start(elapsed - self.delay);
27378   }
27379
27380   function start(elapsed) {
27381     var i, j, n, o;
27382
27383     // If the state is not SCHEDULED, then we previously errored on start.
27384     if (self.state !== SCHEDULED) return stop();
27385
27386     for (i in schedules) {
27387       o = schedules[i];
27388       if (o.name !== self.name) continue;
27389
27390       // While this element already has a starting transition during this frame,
27391       // defer starting an interrupting transition until that transition has a
27392       // chance to tick (and possibly end); see d3/d3-transition#54!
27393       if (o.state === STARTED) return timeout$1(start);
27394
27395       // Interrupt the active transition, if any.
27396       // Dispatch the interrupt event.
27397       if (o.state === RUNNING) {
27398         o.state = ENDED;
27399         o.timer.stop();
27400         o.on.call("interrupt", node, node.__data__, o.index, o.group);
27401         delete schedules[i];
27402       }
27403
27404       // Cancel any pre-empted transitions. No interrupt event is dispatched
27405       // because the cancelled transitions never started. Note that this also
27406       // removes this transition from the pending list!
27407       else if (+i < id) {
27408         o.state = ENDED;
27409         o.timer.stop();
27410         delete schedules[i];
27411       }
27412     }
27413
27414     // Defer the first tick to end of the current frame; see d3/d3#1576.
27415     // Note the transition may be canceled after start and before the first tick!
27416     // Note this must be scheduled before the start event; see d3/d3-transition#16!
27417     // Assuming this is successful, subsequent callbacks go straight to tick.
27418     timeout$1(function() {
27419       if (self.state === STARTED) {
27420         self.state = RUNNING;
27421         self.timer.restart(tick, self.delay, self.time);
27422         tick(elapsed);
27423       }
27424     });
27425
27426     // Dispatch the start event.
27427     // Note this must be done before the tween are initialized.
27428     self.state = STARTING;
27429     self.on.call("start", node, node.__data__, self.index, self.group);
27430     if (self.state !== STARTING) return; // interrupted
27431     self.state = STARTED;
27432
27433     // Initialize the tween, deleting null tween.
27434     tween = new Array(n = self.tween.length);
27435     for (i = 0, j = -1; i < n; ++i) {
27436       if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
27437         tween[++j] = o;
27438       }
27439     }
27440     tween.length = j + 1;
27441   }
27442
27443   function tick(elapsed) {
27444     var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
27445         i = -1,
27446         n = tween.length;
27447
27448     while (++i < n) {
27449       tween[i].call(null, t);
27450     }
27451
27452     // Dispatch the end event.
27453     if (self.state === ENDING) {
27454       self.on.call("end", node, node.__data__, self.index, self.group);
27455       stop();
27456     }
27457   }
27458
27459   function stop() {
27460     self.state = ENDED;
27461     self.timer.stop();
27462     delete schedules[id];
27463     for (var i in schedules) return; // eslint-disable-line no-unused-vars
27464     delete node.__transition;
27465   }
27466 }
27467
27468 var interrupt = function(node, name) {
27469   var schedules = node.__transition,
27470       schedule,
27471       active,
27472       empty = true,
27473       i;
27474
27475   if (!schedules) return;
27476
27477   name = name == null ? null : name + "";
27478
27479   for (i in schedules) {
27480     if ((schedule = schedules[i]).name !== name) { empty = false; continue; }
27481     active = schedule.state > STARTING && schedule.state < ENDING;
27482     schedule.state = ENDED;
27483     schedule.timer.stop();
27484     if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group);
27485     delete schedules[i];
27486   }
27487
27488   if (empty) delete node.__transition;
27489 };
27490
27491 var selection_interrupt = function(name) {
27492   return this.each(function() {
27493     interrupt(this, name);
27494   });
27495 };
27496
27497 function tweenRemove(id, name) {
27498   var tween0, tween1;
27499   return function() {
27500     var schedule = set$3(this, id),
27501         tween = schedule.tween;
27502
27503     // If this node shared tween with the previous node,
27504     // just assign the updated shared tween and we’re done!
27505     // Otherwise, copy-on-write.
27506     if (tween !== tween0) {
27507       tween1 = tween0 = tween;
27508       for (var i = 0, n = tween1.length; i < n; ++i) {
27509         if (tween1[i].name === name) {
27510           tween1 = tween1.slice();
27511           tween1.splice(i, 1);
27512           break;
27513         }
27514       }
27515     }
27516
27517     schedule.tween = tween1;
27518   };
27519 }
27520
27521 function tweenFunction(id, name, value) {
27522   var tween0, tween1;
27523   if (typeof value !== "function") throw new Error;
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).slice();
27533       for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) {
27534         if (tween1[i].name === name) {
27535           tween1[i] = t;
27536           break;
27537         }
27538       }
27539       if (i === n) tween1.push(t);
27540     }
27541
27542     schedule.tween = tween1;
27543   };
27544 }
27545
27546 var transition_tween = function(name, value) {
27547   var id = this._id;
27548
27549   name += "";
27550
27551   if (arguments.length < 2) {
27552     var tween = get$1(this.node(), id).tween;
27553     for (var i = 0, n = tween.length, t; i < n; ++i) {
27554       if ((t = tween[i]).name === name) {
27555         return t.value;
27556       }
27557     }
27558     return null;
27559   }
27560
27561   return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
27562 };
27563
27564 function tweenValue(transition, name, value) {
27565   var id = transition._id;
27566
27567   transition.each(function() {
27568     var schedule = set$3(this, id);
27569     (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
27570   });
27571
27572   return function(node) {
27573     return get$1(node, id).value[name];
27574   };
27575 }
27576
27577 var interpolate$1 = function(a, b) {
27578   var c;
27579   return (typeof b === "number" ? interpolateNumber
27580       : b instanceof color ? interpolateRgb
27581       : (c = color(b)) ? (b = c, interpolateRgb)
27582       : interpolateString)(a, b);
27583 };
27584
27585 function attrRemove$1(name) {
27586   return function() {
27587     this.removeAttribute(name);
27588   };
27589 }
27590
27591 function attrRemoveNS$1(fullname) {
27592   return function() {
27593     this.removeAttributeNS(fullname.space, fullname.local);
27594   };
27595 }
27596
27597 function attrConstant$1(name, interpolate$$1, value1) {
27598   var value00,
27599       interpolate0;
27600   return function() {
27601     var value0 = this.getAttribute(name);
27602     return value0 === value1 ? null
27603         : value0 === value00 ? interpolate0
27604         : interpolate0 = interpolate$$1(value00 = value0, value1);
27605   };
27606 }
27607
27608 function attrConstantNS$1(fullname, interpolate$$1, value1) {
27609   var value00,
27610       interpolate0;
27611   return function() {
27612     var value0 = this.getAttributeNS(fullname.space, fullname.local);
27613     return value0 === value1 ? null
27614         : value0 === value00 ? interpolate0
27615         : interpolate0 = interpolate$$1(value00 = value0, value1);
27616   };
27617 }
27618
27619 function attrFunction$1(name, interpolate$$1, value) {
27620   var value00,
27621       value10,
27622       interpolate0;
27623   return function() {
27624     var value0, value1 = value(this);
27625     if (value1 == null) return void this.removeAttribute(name);
27626     value0 = this.getAttribute(name);
27627     return value0 === value1 ? null
27628         : value0 === value00 && value1 === value10 ? interpolate0
27629         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27630   };
27631 }
27632
27633 function attrFunctionNS$1(fullname, interpolate$$1, value) {
27634   var value00,
27635       value10,
27636       interpolate0;
27637   return function() {
27638     var value0, value1 = value(this);
27639     if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
27640     value0 = this.getAttributeNS(fullname.space, fullname.local);
27641     return value0 === value1 ? null
27642         : value0 === value00 && value1 === value10 ? interpolate0
27643         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27644   };
27645 }
27646
27647 var transition_attr = function(name, value) {
27648   var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$1;
27649   return this.attrTween(name, typeof value === "function"
27650       ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value))
27651       : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname)
27652       : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value));
27653 };
27654
27655 function attrTweenNS(fullname, value) {
27656   function tween() {
27657     var node = this, i = value.apply(node, arguments);
27658     return i && function(t) {
27659       node.setAttributeNS(fullname.space, fullname.local, i(t));
27660     };
27661   }
27662   tween._value = value;
27663   return tween;
27664 }
27665
27666 function attrTween(name, value) {
27667   function tween() {
27668     var node = this, i = value.apply(node, arguments);
27669     return i && function(t) {
27670       node.setAttribute(name, i(t));
27671     };
27672   }
27673   tween._value = value;
27674   return tween;
27675 }
27676
27677 var transition_attrTween = function(name, value) {
27678   var key = "attr." + name;
27679   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
27680   if (value == null) return this.tween(key, null);
27681   if (typeof value !== "function") throw new Error;
27682   var fullname = namespace(name);
27683   return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
27684 };
27685
27686 function delayFunction(id, value) {
27687   return function() {
27688     init(this, id).delay = +value.apply(this, arguments);
27689   };
27690 }
27691
27692 function delayConstant(id, value) {
27693   return value = +value, function() {
27694     init(this, id).delay = value;
27695   };
27696 }
27697
27698 var transition_delay = function(value) {
27699   var id = this._id;
27700
27701   return arguments.length
27702       ? this.each((typeof value === "function"
27703           ? delayFunction
27704           : delayConstant)(id, value))
27705       : get$1(this.node(), id).delay;
27706 };
27707
27708 function durationFunction(id, value) {
27709   return function() {
27710     set$3(this, id).duration = +value.apply(this, arguments);
27711   };
27712 }
27713
27714 function durationConstant(id, value) {
27715   return value = +value, function() {
27716     set$3(this, id).duration = value;
27717   };
27718 }
27719
27720 var transition_duration = function(value) {
27721   var id = this._id;
27722
27723   return arguments.length
27724       ? this.each((typeof value === "function"
27725           ? durationFunction
27726           : durationConstant)(id, value))
27727       : get$1(this.node(), id).duration;
27728 };
27729
27730 function easeConstant(id, value) {
27731   if (typeof value !== "function") throw new Error;
27732   return function() {
27733     set$3(this, id).ease = value;
27734   };
27735 }
27736
27737 var transition_ease = function(value) {
27738   var id = this._id;
27739
27740   return arguments.length
27741       ? this.each(easeConstant(id, value))
27742       : get$1(this.node(), id).ease;
27743 };
27744
27745 var transition_filter = function(match) {
27746   if (typeof match !== "function") match = matcher$1(match);
27747
27748   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
27749     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
27750       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
27751         subgroup.push(node);
27752       }
27753     }
27754   }
27755
27756   return new Transition(subgroups, this._parents, this._name, this._id);
27757 };
27758
27759 var transition_merge = function(transition) {
27760   if (transition._id !== this._id) throw new Error;
27761
27762   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) {
27763     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
27764       if (node = group0[i] || group1[i]) {
27765         merge[i] = node;
27766       }
27767     }
27768   }
27769
27770   for (; j < m0; ++j) {
27771     merges[j] = groups0[j];
27772   }
27773
27774   return new Transition(merges, this._parents, this._name, this._id);
27775 };
27776
27777 function start$1(name) {
27778   return (name + "").trim().split(/^|\s+/).every(function(t) {
27779     var i = t.indexOf(".");
27780     if (i >= 0) t = t.slice(0, i);
27781     return !t || t === "start";
27782   });
27783 }
27784
27785 function onFunction(id, name, listener) {
27786   var on0, on1, sit = start$1(name) ? init : set$3;
27787   return function() {
27788     var schedule = sit(this, id),
27789         on = schedule.on;
27790
27791     // If this node shared a dispatch with the previous node,
27792     // just assign the updated shared dispatch and we’re done!
27793     // Otherwise, copy-on-write.
27794     if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
27795
27796     schedule.on = on1;
27797   };
27798 }
27799
27800 var transition_on = function(name, listener) {
27801   var id = this._id;
27802
27803   return arguments.length < 2
27804       ? get$1(this.node(), id).on.on(name)
27805       : this.each(onFunction(id, name, listener));
27806 };
27807
27808 function removeFunction(id) {
27809   return function() {
27810     var parent = this.parentNode;
27811     for (var i in this.__transition) if (+i !== id) return;
27812     if (parent) parent.removeChild(this);
27813   };
27814 }
27815
27816 var transition_remove = function() {
27817   return this.on("end.remove", removeFunction(this._id));
27818 };
27819
27820 var transition_select = function(select$$1) {
27821   var name = this._name,
27822       id = this._id;
27823
27824   if (typeof select$$1 !== "function") select$$1 = selector(select$$1);
27825
27826   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
27827     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
27828       if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) {
27829         if ("__data__" in node) subnode.__data__ = node.__data__;
27830         subgroup[i] = subnode;
27831         schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
27832       }
27833     }
27834   }
27835
27836   return new Transition(subgroups, this._parents, name, id);
27837 };
27838
27839 var transition_selectAll = function(select$$1) {
27840   var name = this._name,
27841       id = this._id;
27842
27843   if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1);
27844
27845   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
27846     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
27847       if (node = group[i]) {
27848         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) {
27849           if (child = children[k]) {
27850             schedule(child, name, id, k, children, inherit);
27851           }
27852         }
27853         subgroups.push(children);
27854         parents.push(node);
27855       }
27856     }
27857   }
27858
27859   return new Transition(subgroups, parents, name, id);
27860 };
27861
27862 var Selection$1 = selection.prototype.constructor;
27863
27864 var transition_selection = function() {
27865   return new Selection$1(this._groups, this._parents);
27866 };
27867
27868 function styleRemove$1(name, interpolate$$1) {
27869   var value00,
27870       value10,
27871       interpolate0;
27872   return function() {
27873     var style = window$1(this).getComputedStyle(this, null),
27874         value0 = style.getPropertyValue(name),
27875         value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
27876     return value0 === value1 ? null
27877         : value0 === value00 && value1 === value10 ? interpolate0
27878         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27879   };
27880 }
27881
27882 function styleRemoveEnd(name) {
27883   return function() {
27884     this.style.removeProperty(name);
27885   };
27886 }
27887
27888 function styleConstant$1(name, interpolate$$1, value1) {
27889   var value00,
27890       interpolate0;
27891   return function() {
27892     var value0 = window$1(this).getComputedStyle(this, null).getPropertyValue(name);
27893     return value0 === value1 ? null
27894         : value0 === value00 ? interpolate0
27895         : interpolate0 = interpolate$$1(value00 = value0, value1);
27896   };
27897 }
27898
27899 function styleFunction$1(name, interpolate$$1, value) {
27900   var value00,
27901       value10,
27902       interpolate0;
27903   return function() {
27904     var style = window$1(this).getComputedStyle(this, null),
27905         value0 = style.getPropertyValue(name),
27906         value1 = value(this);
27907     if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
27908     return value0 === value1 ? null
27909         : value0 === value00 && value1 === value10 ? interpolate0
27910         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27911   };
27912 }
27913
27914 var transition_style = function(name, value, priority) {
27915   var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$1;
27916   return value == null ? this
27917           .styleTween(name, styleRemove$1(name, i))
27918           .on("end.style." + name, styleRemoveEnd(name))
27919       : this.styleTween(name, typeof value === "function"
27920           ? styleFunction$1(name, i, tweenValue(this, "style." + name, value))
27921           : styleConstant$1(name, i, value), priority);
27922 };
27923
27924 function styleTween(name, value, priority) {
27925   function tween() {
27926     var node = this, i = value.apply(node, arguments);
27927     return i && function(t) {
27928       node.style.setProperty(name, i(t), priority);
27929     };
27930   }
27931   tween._value = value;
27932   return tween;
27933 }
27934
27935 var transition_styleTween = function(name, value, priority) {
27936   var key = "style." + (name += "");
27937   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
27938   if (value == null) return this.tween(key, null);
27939   if (typeof value !== "function") throw new Error;
27940   return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
27941 };
27942
27943 function textConstant$1(value) {
27944   return function() {
27945     this.textContent = value;
27946   };
27947 }
27948
27949 function textFunction$1(value) {
27950   return function() {
27951     var value1 = value(this);
27952     this.textContent = value1 == null ? "" : value1;
27953   };
27954 }
27955
27956 var transition_text = function(value) {
27957   return this.tween("text", typeof value === "function"
27958       ? textFunction$1(tweenValue(this, "text", value))
27959       : textConstant$1(value == null ? "" : value + ""));
27960 };
27961
27962 var transition_transition = function() {
27963   var name = this._name,
27964       id0 = this._id,
27965       id1 = newId();
27966
27967   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
27968     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
27969       if (node = group[i]) {
27970         var inherit = get$1(node, id0);
27971         schedule(node, name, id1, i, group, {
27972           time: inherit.time + inherit.delay + inherit.duration,
27973           delay: 0,
27974           duration: inherit.duration,
27975           ease: inherit.ease
27976         });
27977       }
27978     }
27979   }
27980
27981   return new Transition(groups, this._parents, name, id1);
27982 };
27983
27984 var id = 0;
27985
27986 function Transition(groups, parents, name, id) {
27987   this._groups = groups;
27988   this._parents = parents;
27989   this._name = name;
27990   this._id = id;
27991 }
27992
27993 function transition(name) {
27994   return selection().transition(name);
27995 }
27996
27997 function newId() {
27998   return ++id;
27999 }
28000
28001 var selection_prototype = selection.prototype;
28002
28003 Transition.prototype = transition.prototype = {
28004   constructor: Transition,
28005   select: transition_select,
28006   selectAll: transition_selectAll,
28007   filter: transition_filter,
28008   merge: transition_merge,
28009   selection: transition_selection,
28010   transition: transition_transition,
28011   call: selection_prototype.call,
28012   nodes: selection_prototype.nodes,
28013   node: selection_prototype.node,
28014   size: selection_prototype.size,
28015   empty: selection_prototype.empty,
28016   each: selection_prototype.each,
28017   on: transition_on,
28018   attr: transition_attr,
28019   attrTween: transition_attrTween,
28020   style: transition_style,
28021   styleTween: transition_styleTween,
28022   text: transition_text,
28023   remove: transition_remove,
28024   tween: transition_tween,
28025   delay: transition_delay,
28026   duration: transition_duration,
28027   ease: transition_ease
28028 };
28029
28030 var defaultTiming = {
28031   time: null, // Set on use.
28032   delay: 0,
28033   duration: 250,
28034   ease: cubicInOut
28035 };
28036
28037 function inherit(node, id) {
28038   var timing;
28039   while (!(timing = node.__transition) || !(timing = timing[id])) {
28040     if (!(node = node.parentNode)) {
28041       return defaultTiming.time = now(), defaultTiming;
28042     }
28043   }
28044   return timing;
28045 }
28046
28047 var selection_transition = function(name) {
28048   var id,
28049       timing;
28050
28051   if (name instanceof Transition) {
28052     id = name._id, name = name._name;
28053   } else {
28054     id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
28055   }
28056
28057   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
28058     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
28059       if (node = group[i]) {
28060         schedule(node, name, id, i, group, timing || inherit(node, id));
28061       }
28062     }
28063   }
28064
28065   return new Transition(groups, this._parents, name, id);
28066 };
28067
28068 selection.prototype.interrupt = selection_interrupt;
28069 selection.prototype.transition = selection_transition;
28070
28071 var root$1 = [null];
28072
28073 var active = function(node, name) {
28074   var schedules = node.__transition,
28075       schedule,
28076       i;
28077
28078   if (schedules) {
28079     name = name == null ? null : name + "";
28080     for (i in schedules) {
28081       if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) {
28082         return new Transition([[node]], root$1, name, +i);
28083       }
28084     }
28085   }
28086
28087   return null;
28088 };
28089
28090 var slice$4 = Array.prototype.slice;
28091
28092 var identity$5 = function(x) {
28093   return x;
28094 };
28095
28096 var top = 1;
28097 var right = 2;
28098 var bottom = 3;
28099 var left = 4;
28100 var epsilon$2 = 1e-6;
28101
28102 function translateX(scale0, scale1, d) {
28103   var x = scale0(d);
28104   return "translate(" + (isFinite(x) ? x : scale1(d)) + ",0)";
28105 }
28106
28107 function translateY(scale0, scale1, d) {
28108   var y = scale0(d);
28109   return "translate(0," + (isFinite(y) ? y : scale1(d)) + ")";
28110 }
28111
28112 function center(scale) {
28113   var offset = scale.bandwidth() / 2;
28114   if (scale.round()) offset = Math.round(offset);
28115   return function(d) {
28116     return scale(d) + offset;
28117   };
28118 }
28119
28120 function entering() {
28121   return !this.__axis;
28122 }
28123
28124 function axis(orient, scale) {
28125   var tickArguments = [],
28126       tickValues = null,
28127       tickFormat = null,
28128       tickSizeInner = 6,
28129       tickSizeOuter = 6,
28130       tickPadding = 3;
28131
28132   function axis(context) {
28133     var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
28134         format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$5) : tickFormat,
28135         spacing = Math.max(tickSizeInner, 0) + tickPadding,
28136         transform = orient === top || orient === bottom ? translateX : translateY,
28137         range = scale.range(),
28138         range0 = range[0] + 0.5,
28139         range1 = range[range.length - 1] + 0.5,
28140         position = (scale.bandwidth ? center : identity$5)(scale.copy()),
28141         selection = context.selection ? context.selection() : context,
28142         path = selection.selectAll(".domain").data([null]),
28143         tick = selection.selectAll(".tick").data(values, scale).order(),
28144         tickExit = tick.exit(),
28145         tickEnter = tick.enter().append("g").attr("class", "tick"),
28146         line = tick.select("line"),
28147         text = tick.select("text"),
28148         k = orient === top || orient === left ? -1 : 1,
28149         x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x");
28150
28151     path = path.merge(path.enter().insert("path", ".tick")
28152         .attr("class", "domain")
28153         .attr("stroke", "#000"));
28154
28155     tick = tick.merge(tickEnter);
28156
28157     line = line.merge(tickEnter.append("line")
28158         .attr("stroke", "#000")
28159         .attr(x + "2", k * tickSizeInner)
28160         .attr(y + "1", 0.5)
28161         .attr(y + "2", 0.5));
28162
28163     text = text.merge(tickEnter.append("text")
28164         .attr("fill", "#000")
28165         .attr(x, k * spacing)
28166         .attr(y, 0.5)
28167         .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
28168
28169     if (context !== selection) {
28170       path = path.transition(context);
28171       tick = tick.transition(context);
28172       line = line.transition(context);
28173       text = text.transition(context);
28174
28175       tickExit = tickExit.transition(context)
28176           .attr("opacity", epsilon$2)
28177           .attr("transform", function(d) { return transform(position, this.parentNode.__axis || position, d); });
28178
28179       tickEnter
28180           .attr("opacity", epsilon$2)
28181           .attr("transform", function(d) { return transform(this.parentNode.__axis || position, position, d); });
28182     }
28183
28184     tickExit.remove();
28185
28186     path
28187         .attr("d", orient === left || orient == right
28188             ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter
28189             : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter);
28190
28191     tick
28192         .attr("opacity", 1)
28193         .attr("transform", function(d) { return transform(position, position, d); });
28194
28195     line
28196         .attr(x + "2", k * tickSizeInner);
28197
28198     text
28199         .attr(x, k * spacing)
28200         .text(format);
28201
28202     selection.filter(entering)
28203         .attr("fill", "none")
28204         .attr("font-size", 10)
28205         .attr("font-family", "sans-serif")
28206         .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
28207
28208     selection
28209         .each(function() { this.__axis = position; });
28210   }
28211
28212   axis.scale = function(_) {
28213     return arguments.length ? (scale = _, axis) : scale;
28214   };
28215
28216   axis.ticks = function() {
28217     return tickArguments = slice$4.call(arguments), axis;
28218   };
28219
28220   axis.tickArguments = function(_) {
28221     return arguments.length ? (tickArguments = _ == null ? [] : slice$4.call(_), axis) : tickArguments.slice();
28222   };
28223
28224   axis.tickValues = function(_) {
28225     return arguments.length ? (tickValues = _ == null ? null : slice$4.call(_), axis) : tickValues && tickValues.slice();
28226   };
28227
28228   axis.tickFormat = function(_) {
28229     return arguments.length ? (tickFormat = _, axis) : tickFormat;
28230   };
28231
28232   axis.tickSize = function(_) {
28233     return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
28234   };
28235
28236   axis.tickSizeInner = function(_) {
28237     return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
28238   };
28239
28240   axis.tickSizeOuter = function(_) {
28241     return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
28242   };
28243
28244   axis.tickPadding = function(_) {
28245     return arguments.length ? (tickPadding = +_, axis) : tickPadding;
28246   };
28247
28248   return axis;
28249 }
28250
28251 function axisTop(scale) {
28252   return axis(top, scale);
28253 }
28254
28255 function axisRight(scale) {
28256   return axis(right, scale);
28257 }
28258
28259 function axisBottom(scale) {
28260   return axis(bottom, scale);
28261 }
28262
28263 function axisLeft(scale) {
28264   return axis(left, scale);
28265 }
28266
28267 function defaultSeparation(a, b) {
28268   return a.parent === b.parent ? 1 : 2;
28269 }
28270
28271 function meanX(children) {
28272   return children.reduce(meanXReduce, 0) / children.length;
28273 }
28274
28275 function meanXReduce(x, c) {
28276   return x + c.x;
28277 }
28278
28279 function maxY(children) {
28280   return 1 + children.reduce(maxYReduce, 0);
28281 }
28282
28283 function maxYReduce(y, c) {
28284   return Math.max(y, c.y);
28285 }
28286
28287 function leafLeft(node) {
28288   var children;
28289   while (children = node.children) node = children[0];
28290   return node;
28291 }
28292
28293 function leafRight(node) {
28294   var children;
28295   while (children = node.children) node = children[children.length - 1];
28296   return node;
28297 }
28298
28299 var cluster = function() {
28300   var separation = defaultSeparation,
28301       dx = 1,
28302       dy = 1,
28303       nodeSize = false;
28304
28305   function cluster(root) {
28306     var previousNode,
28307         x = 0;
28308
28309     // First walk, computing the initial x & y values.
28310     root.eachAfter(function(node) {
28311       var children = node.children;
28312       if (children) {
28313         node.x = meanX(children);
28314         node.y = maxY(children);
28315       } else {
28316         node.x = previousNode ? x += separation(node, previousNode) : 0;
28317         node.y = 0;
28318         previousNode = node;
28319       }
28320     });
28321
28322     var left = leafLeft(root),
28323         right = leafRight(root),
28324         x0 = left.x - separation(left, right) / 2,
28325         x1 = right.x + separation(right, left) / 2;
28326
28327     // Second walk, normalizing x & y to the desired size.
28328     return root.eachAfter(nodeSize ? function(node) {
28329       node.x = (node.x - root.x) * dx;
28330       node.y = (root.y - node.y) * dy;
28331     } : function(node) {
28332       node.x = (node.x - x0) / (x1 - x0) * dx;
28333       node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
28334     });
28335   }
28336
28337   cluster.separation = function(x) {
28338     return arguments.length ? (separation = x, cluster) : separation;
28339   };
28340
28341   cluster.size = function(x) {
28342     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
28343   };
28344
28345   cluster.nodeSize = function(x) {
28346     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
28347   };
28348
28349   return cluster;
28350 };
28351
28352 var node_each = function(callback) {
28353   var node = this, current, next = [node], children, i, n;
28354   do {
28355     current = next.reverse(), next = [];
28356     while (node = current.pop()) {
28357       callback(node), children = node.children;
28358       if (children) for (i = 0, n = children.length; i < n; ++i) {
28359         next.push(children[i]);
28360       }
28361     }
28362   } while (next.length);
28363   return this;
28364 };
28365
28366 var node_eachBefore = function(callback) {
28367   var node = this, nodes = [node], children, i;
28368   while (node = nodes.pop()) {
28369     callback(node), children = node.children;
28370     if (children) for (i = children.length - 1; i >= 0; --i) {
28371       nodes.push(children[i]);
28372     }
28373   }
28374   return this;
28375 };
28376
28377 var node_eachAfter = function(callback) {
28378   var node = this, nodes = [node], next = [], children, i, n;
28379   while (node = nodes.pop()) {
28380     next.push(node), children = node.children;
28381     if (children) for (i = 0, n = children.length; i < n; ++i) {
28382       nodes.push(children[i]);
28383     }
28384   }
28385   while (node = next.pop()) {
28386     callback(node);
28387   }
28388   return this;
28389 };
28390
28391 var node_sum = function(value) {
28392   return this.eachAfter(function(node) {
28393     var sum = +value(node.data) || 0,
28394         children = node.children,
28395         i = children && children.length;
28396     while (--i >= 0) sum += children[i].value;
28397     node.value = sum;
28398   });
28399 };
28400
28401 var node_sort = function(compare) {
28402   return this.eachBefore(function(node) {
28403     if (node.children) {
28404       node.children.sort(compare);
28405     }
28406   });
28407 };
28408
28409 var node_path = function(end) {
28410   var start = this,
28411       ancestor = leastCommonAncestor(start, end),
28412       nodes = [start];
28413   while (start !== ancestor) {
28414     start = start.parent;
28415     nodes.push(start);
28416   }
28417   var k = nodes.length;
28418   while (end !== ancestor) {
28419     nodes.splice(k, 0, end);
28420     end = end.parent;
28421   }
28422   return nodes;
28423 };
28424
28425 function leastCommonAncestor(a, b) {
28426   if (a === b) return a;
28427   var aNodes = a.ancestors(),
28428       bNodes = b.ancestors(),
28429       c = null;
28430   a = aNodes.pop();
28431   b = bNodes.pop();
28432   while (a === b) {
28433     c = a;
28434     a = aNodes.pop();
28435     b = bNodes.pop();
28436   }
28437   return c;
28438 }
28439
28440 var node_ancestors = function() {
28441   var node = this, nodes = [node];
28442   while (node = node.parent) {
28443     nodes.push(node);
28444   }
28445   return nodes;
28446 };
28447
28448 var node_descendants = function() {
28449   var nodes = [];
28450   this.each(function(node) {
28451     nodes.push(node);
28452   });
28453   return nodes;
28454 };
28455
28456 var node_leaves = function() {
28457   var leaves = [];
28458   this.eachBefore(function(node) {
28459     if (!node.children) {
28460       leaves.push(node);
28461     }
28462   });
28463   return leaves;
28464 };
28465
28466 var node_links = function() {
28467   var root = this, links = [];
28468   root.each(function(node) {
28469     if (node !== root) { // Don’t include the root’s parent, if any.
28470       links.push({source: node.parent, target: node});
28471     }
28472   });
28473   return links;
28474 };
28475
28476 function hierarchy(data, children) {
28477   var root = new Node(data),
28478       valued = +data.value && (root.value = data.value),
28479       node,
28480       nodes = [root],
28481       child,
28482       childs,
28483       i,
28484       n;
28485
28486   if (children == null) children = defaultChildren;
28487
28488   while (node = nodes.pop()) {
28489     if (valued) node.value = +node.data.value;
28490     if ((childs = children(node.data)) && (n = childs.length)) {
28491       node.children = new Array(n);
28492       for (i = n - 1; i >= 0; --i) {
28493         nodes.push(child = node.children[i] = new Node(childs[i]));
28494         child.parent = node;
28495         child.depth = node.depth + 1;
28496       }
28497     }
28498   }
28499
28500   return root.eachBefore(computeHeight);
28501 }
28502
28503 function node_copy() {
28504   return hierarchy(this).eachBefore(copyData);
28505 }
28506
28507 function defaultChildren(d) {
28508   return d.children;
28509 }
28510
28511 function copyData(node) {
28512   node.data = node.data.data;
28513 }
28514
28515 function computeHeight(node) {
28516   var height = 0;
28517   do node.height = height;
28518   while ((node = node.parent) && (node.height < ++height));
28519 }
28520
28521 function Node(data) {
28522   this.data = data;
28523   this.depth =
28524   this.height = 0;
28525   this.parent = null;
28526 }
28527
28528 Node.prototype = hierarchy.prototype = {
28529   constructor: Node,
28530   each: node_each,
28531   eachAfter: node_eachAfter,
28532   eachBefore: node_eachBefore,
28533   sum: node_sum,
28534   sort: node_sort,
28535   path: node_path,
28536   ancestors: node_ancestors,
28537   descendants: node_descendants,
28538   leaves: node_leaves,
28539   links: node_links,
28540   copy: node_copy
28541 };
28542
28543 function Node$2(value) {
28544   this._ = value;
28545   this.next = null;
28546 }
28547
28548 var shuffle$1 = function(array) {
28549   var i,
28550       n = (array = array.slice()).length,
28551       head = null,
28552       node = head;
28553
28554   while (n) {
28555     var next = new Node$2(array[n - 1]);
28556     if (node) node = node.next = next;
28557     else node = head = next;
28558     array[i] = array[--n];
28559   }
28560
28561   return {
28562     head: head,
28563     tail: node
28564   };
28565 };
28566
28567 var enclose = function(circles) {
28568   return encloseN(shuffle$1(circles), []);
28569 };
28570
28571 function encloses(a, b) {
28572   var dx = b.x - a.x,
28573       dy = b.y - a.y,
28574       dr = a.r - b.r;
28575   return dr * dr + 1e-6 > dx * dx + dy * dy;
28576 }
28577
28578 // Returns the smallest circle that contains circles L and intersects circles B.
28579 function encloseN(L, B) {
28580   var circle,
28581       l0 = null,
28582       l1 = L.head,
28583       l2,
28584       p1;
28585
28586   switch (B.length) {
28587     case 1: circle = enclose1(B[0]); break;
28588     case 2: circle = enclose2(B[0], B[1]); break;
28589     case 3: circle = enclose3(B[0], B[1], B[2]); break;
28590   }
28591
28592   while (l1) {
28593     p1 = l1._, l2 = l1.next;
28594     if (!circle || !encloses(circle, p1)) {
28595
28596       // Temporarily truncate L before l1.
28597       if (l0) L.tail = l0, l0.next = null;
28598       else L.head = L.tail = null;
28599
28600       B.push(p1);
28601       circle = encloseN(L, B); // Note: reorders L!
28602       B.pop();
28603
28604       // Move l1 to the front of L and reconnect the truncated list L.
28605       if (L.head) l1.next = L.head, L.head = l1;
28606       else l1.next = null, L.head = L.tail = l1;
28607       l0 = L.tail, l0.next = l2;
28608
28609     } else {
28610       l0 = l1;
28611     }
28612     l1 = l2;
28613   }
28614
28615   L.tail = l0;
28616   return circle;
28617 }
28618
28619 function enclose1(a) {
28620   return {
28621     x: a.x,
28622     y: a.y,
28623     r: a.r
28624   };
28625 }
28626
28627 function enclose2(a, b) {
28628   var x1 = a.x, y1 = a.y, r1 = a.r,
28629       x2 = b.x, y2 = b.y, r2 = b.r,
28630       x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
28631       l = Math.sqrt(x21 * x21 + y21 * y21);
28632   return {
28633     x: (x1 + x2 + x21 / l * r21) / 2,
28634     y: (y1 + y2 + y21 / l * r21) / 2,
28635     r: (l + r1 + r2) / 2
28636   };
28637 }
28638
28639 function enclose3(a, b, c) {
28640   var x1 = a.x, y1 = a.y, r1 = a.r,
28641       x2 = b.x, y2 = b.y, r2 = b.r,
28642       x3 = c.x, y3 = c.y, r3 = c.r,
28643       a2 = 2 * (x1 - x2),
28644       b2 = 2 * (y1 - y2),
28645       c2 = 2 * (r2 - r1),
28646       d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
28647       a3 = 2 * (x1 - x3),
28648       b3 = 2 * (y1 - y3),
28649       c3 = 2 * (r3 - r1),
28650       d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
28651       ab = a3 * b2 - a2 * b3,
28652       xa = (b2 * d3 - b3 * d2) / ab - x1,
28653       xb = (b3 * c2 - b2 * c3) / ab,
28654       ya = (a3 * d2 - a2 * d3) / ab - y1,
28655       yb = (a2 * c3 - a3 * c2) / ab,
28656       A = xb * xb + yb * yb - 1,
28657       B = 2 * (xa * xb + ya * yb + r1),
28658       C = xa * xa + ya * ya - r1 * r1,
28659       r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
28660   return {
28661     x: xa + xb * r + x1,
28662     y: ya + yb * r + y1,
28663     r: r
28664   };
28665 }
28666
28667 function place(a, b, c) {
28668   var ax = a.x,
28669       ay = a.y,
28670       da = b.r + c.r,
28671       db = a.r + c.r,
28672       dx = b.x - ax,
28673       dy = b.y - ay,
28674       dc = dx * dx + dy * dy;
28675   if (dc) {
28676     var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
28677         y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
28678     c.x = ax + x * dx + y * dy;
28679     c.y = ay + x * dy - y * dx;
28680   } else {
28681     c.x = ax + db;
28682     c.y = ay;
28683   }
28684 }
28685
28686 function intersects(a, b) {
28687   var dx = b.x - a.x,
28688       dy = b.y - a.y,
28689       dr = a.r + b.r;
28690   return dr * dr > dx * dx + dy * dy;
28691 }
28692
28693 function distance2(circle, x, y) {
28694   var dx = circle.x - x,
28695       dy = circle.y - y;
28696   return dx * dx + dy * dy;
28697 }
28698
28699 function Node$1(circle) {
28700   this._ = circle;
28701   this.next = null;
28702   this.previous = null;
28703 }
28704
28705 function packEnclose(circles) {
28706   if (!(n = circles.length)) return 0;
28707
28708   var a, b, c, n;
28709
28710   // Place the first circle.
28711   a = circles[0], a.x = 0, a.y = 0;
28712   if (!(n > 1)) return a.r;
28713
28714   // Place the second circle.
28715   b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
28716   if (!(n > 2)) return a.r + b.r;
28717
28718   // Place the third circle.
28719   place(b, a, c = circles[2]);
28720
28721   // Initialize the weighted centroid.
28722   var aa = a.r * a.r,
28723       ba = b.r * b.r,
28724       ca = c.r * c.r,
28725       oa = aa + ba + ca,
28726       ox = aa * a.x + ba * b.x + ca * c.x,
28727       oy = aa * a.y + ba * b.y + ca * c.y,
28728       cx, cy, i, j, k, sj, sk;
28729
28730   // Initialize the front-chain using the first three circles a, b and c.
28731   a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
28732   a.next = c.previous = b;
28733   b.next = a.previous = c;
28734   c.next = b.previous = a;
28735
28736   // Attempt to place each remaining circle…
28737   pack: for (i = 3; i < n; ++i) {
28738     place(a._, b._, c = circles[i]), c = new Node$1(c);
28739
28740     // If there are only three elements in the front-chain…
28741     if ((k = a.previous) === (j = b.next)) {
28742       // If the new circle intersects the third circle,
28743       // rotate the front chain to try the next position.
28744       if (intersects(j._, c._)) {
28745         a = b, b = j, --i;
28746         continue pack;
28747       }
28748     }
28749
28750     // Find the closest intersecting circle on the front-chain, if any.
28751     else {
28752       sj = j._.r, sk = k._.r;
28753       do {
28754         if (sj <= sk) {
28755           if (intersects(j._, c._)) {
28756             b = j, a.next = b, b.previous = a, --i;
28757             continue pack;
28758           }
28759           j = j.next, sj += j._.r;
28760         } else {
28761           if (intersects(k._, c._)) {
28762             a = k, a.next = b, b.previous = a, --i;
28763             continue pack;
28764           }
28765           k = k.previous, sk += k._.r;
28766         }
28767       } while (j !== k.next);
28768     }
28769
28770     // Success! Insert the new circle c between a and b.
28771     c.previous = a, c.next = b, a.next = b.previous = b = c;
28772
28773     // Update the weighted centroid.
28774     oa += ca = c._.r * c._.r;
28775     ox += ca * c._.x;
28776     oy += ca * c._.y;
28777
28778     // Compute the new closest circle a to centroid.
28779     aa = distance2(a._, cx = ox / oa, cy = oy / oa);
28780     while ((c = c.next) !== b) {
28781       if ((ca = distance2(c._, cx, cy)) < aa) {
28782         a = c, aa = ca;
28783       }
28784     }
28785     b = a.next;
28786   }
28787
28788   // Compute the enclosing circle of the front chain.
28789   a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
28790
28791   // Translate the circles to put the enclosing circle around the origin.
28792   for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
28793
28794   return c.r;
28795 }
28796
28797 var siblings = function(circles) {
28798   packEnclose(circles);
28799   return circles;
28800 };
28801
28802 function optional(f) {
28803   return f == null ? null : required(f);
28804 }
28805
28806 function required(f) {
28807   if (typeof f !== "function") throw new Error;
28808   return f;
28809 }
28810
28811 function constantZero() {
28812   return 0;
28813 }
28814
28815 var constant$6 = function(x) {
28816   return function() {
28817     return x;
28818   };
28819 };
28820
28821 function defaultRadius(d) {
28822   return Math.sqrt(d.value);
28823 }
28824
28825 var index$2 = function() {
28826   var radius = null,
28827       dx = 1,
28828       dy = 1,
28829       padding = constantZero;
28830
28831   function pack(root) {
28832     root.x = dx / 2, root.y = dy / 2;
28833     if (radius) {
28834       root.eachBefore(radiusLeaf(radius))
28835           .eachAfter(packChildren(padding, 0.5))
28836           .eachBefore(translateChild(1));
28837     } else {
28838       root.eachBefore(radiusLeaf(defaultRadius))
28839           .eachAfter(packChildren(constantZero, 1))
28840           .eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
28841           .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
28842     }
28843     return root;
28844   }
28845
28846   pack.radius = function(x) {
28847     return arguments.length ? (radius = optional(x), pack) : radius;
28848   };
28849
28850   pack.size = function(x) {
28851     return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
28852   };
28853
28854   pack.padding = function(x) {
28855     return arguments.length ? (padding = typeof x === "function" ? x : constant$6(+x), pack) : padding;
28856   };
28857
28858   return pack;
28859 };
28860
28861 function radiusLeaf(radius) {
28862   return function(node) {
28863     if (!node.children) {
28864       node.r = Math.max(0, +radius(node) || 0);
28865     }
28866   };
28867 }
28868
28869 function packChildren(padding, k) {
28870   return function(node) {
28871     if (children = node.children) {
28872       var children,
28873           i,
28874           n = children.length,
28875           r = padding(node) * k || 0,
28876           e;
28877
28878       if (r) for (i = 0; i < n; ++i) children[i].r += r;
28879       e = packEnclose(children);
28880       if (r) for (i = 0; i < n; ++i) children[i].r -= r;
28881       node.r = e + r;
28882     }
28883   };
28884 }
28885
28886 function translateChild(k) {
28887   return function(node) {
28888     var parent = node.parent;
28889     node.r *= k;
28890     if (parent) {
28891       node.x = parent.x + k * node.x;
28892       node.y = parent.y + k * node.y;
28893     }
28894   };
28895 }
28896
28897 var roundNode = function(node) {
28898   node.x0 = Math.round(node.x0);
28899   node.y0 = Math.round(node.y0);
28900   node.x1 = Math.round(node.x1);
28901   node.y1 = Math.round(node.y1);
28902 };
28903
28904 var treemapDice = function(parent, x0, y0, x1, y1) {
28905   var nodes = parent.children,
28906       node,
28907       i = -1,
28908       n = nodes.length,
28909       k = parent.value && (x1 - x0) / parent.value;
28910
28911   while (++i < n) {
28912     node = nodes[i], node.y0 = y0, node.y1 = y1;
28913     node.x0 = x0, node.x1 = x0 += node.value * k;
28914   }
28915 };
28916
28917 var partition = function() {
28918   var dx = 1,
28919       dy = 1,
28920       padding = 0,
28921       round = false;
28922
28923   function partition(root) {
28924     var n = root.height + 1;
28925     root.x0 =
28926     root.y0 = padding;
28927     root.x1 = dx;
28928     root.y1 = dy / n;
28929     root.eachBefore(positionNode(dy, n));
28930     if (round) root.eachBefore(roundNode);
28931     return root;
28932   }
28933
28934   function positionNode(dy, n) {
28935     return function(node) {
28936       if (node.children) {
28937         treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
28938       }
28939       var x0 = node.x0,
28940           y0 = node.y0,
28941           x1 = node.x1 - padding,
28942           y1 = node.y1 - padding;
28943       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
28944       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
28945       node.x0 = x0;
28946       node.y0 = y0;
28947       node.x1 = x1;
28948       node.y1 = y1;
28949     };
28950   }
28951
28952   partition.round = function(x) {
28953     return arguments.length ? (round = !!x, partition) : round;
28954   };
28955
28956   partition.size = function(x) {
28957     return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
28958   };
28959
28960   partition.padding = function(x) {
28961     return arguments.length ? (padding = +x, partition) : padding;
28962   };
28963
28964   return partition;
28965 };
28966
28967 var keyPrefix$1 = "$";
28968 var preroot = {depth: -1};
28969 var ambiguous = {};
28970
28971 function defaultId(d) {
28972   return d.id;
28973 }
28974
28975 function defaultParentId(d) {
28976   return d.parentId;
28977 }
28978
28979 var stratify = function() {
28980   var id = defaultId,
28981       parentId = defaultParentId;
28982
28983   function stratify(data) {
28984     var d,
28985         i,
28986         n = data.length,
28987         root,
28988         parent,
28989         node,
28990         nodes = new Array(n),
28991         nodeId,
28992         nodeKey,
28993         nodeByKey = {};
28994
28995     for (i = 0; i < n; ++i) {
28996       d = data[i], node = nodes[i] = new Node(d);
28997       if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
28998         nodeKey = keyPrefix$1 + (node.id = nodeId);
28999         nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
29000       }
29001     }
29002
29003     for (i = 0; i < n; ++i) {
29004       node = nodes[i], nodeId = parentId(data[i], i, data);
29005       if (nodeId == null || !(nodeId += "")) {
29006         if (root) throw new Error("multiple roots");
29007         root = node;
29008       } else {
29009         parent = nodeByKey[keyPrefix$1 + nodeId];
29010         if (!parent) throw new Error("missing: " + nodeId);
29011         if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
29012         if (parent.children) parent.children.push(node);
29013         else parent.children = [node];
29014         node.parent = parent;
29015       }
29016     }
29017
29018     if (!root) throw new Error("no root");
29019     root.parent = preroot;
29020     root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
29021     root.parent = null;
29022     if (n > 0) throw new Error("cycle");
29023
29024     return root;
29025   }
29026
29027   stratify.id = function(x) {
29028     return arguments.length ? (id = required(x), stratify) : id;
29029   };
29030
29031   stratify.parentId = function(x) {
29032     return arguments.length ? (parentId = required(x), stratify) : parentId;
29033   };
29034
29035   return stratify;
29036 };
29037
29038 function defaultSeparation$1(a, b) {
29039   return a.parent === b.parent ? 1 : 2;
29040 }
29041
29042 // function radialSeparation(a, b) {
29043 //   return (a.parent === b.parent ? 1 : 2) / a.depth;
29044 // }
29045
29046 // This function is used to traverse the left contour of a subtree (or
29047 // subforest). It returns the successor of v on this contour. This successor is
29048 // either given by the leftmost child of v or by the thread of v. The function
29049 // returns null if and only if v is on the highest level of its subtree.
29050 function nextLeft(v) {
29051   var children = v.children;
29052   return children ? children[0] : v.t;
29053 }
29054
29055 // This function works analogously to nextLeft.
29056 function nextRight(v) {
29057   var children = v.children;
29058   return children ? children[children.length - 1] : v.t;
29059 }
29060
29061 // Shifts the current subtree rooted at w+. This is done by increasing
29062 // prelim(w+) and mod(w+) by shift.
29063 function moveSubtree(wm, wp, shift) {
29064   var change = shift / (wp.i - wm.i);
29065   wp.c -= change;
29066   wp.s += shift;
29067   wm.c += change;
29068   wp.z += shift;
29069   wp.m += shift;
29070 }
29071
29072 // All other shifts, applied to the smaller subtrees between w- and w+, are
29073 // performed by this function. To prepare the shifts, we have to adjust
29074 // change(w+), shift(w+), and change(w-).
29075 function executeShifts(v) {
29076   var shift = 0,
29077       change = 0,
29078       children = v.children,
29079       i = children.length,
29080       w;
29081   while (--i >= 0) {
29082     w = children[i];
29083     w.z += shift;
29084     w.m += shift;
29085     shift += w.s + (change += w.c);
29086   }
29087 }
29088
29089 // If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
29090 // returns the specified (default) ancestor.
29091 function nextAncestor(vim, v, ancestor) {
29092   return vim.a.parent === v.parent ? vim.a : ancestor;
29093 }
29094
29095 function TreeNode(node, i) {
29096   this._ = node;
29097   this.parent = null;
29098   this.children = null;
29099   this.A = null; // default ancestor
29100   this.a = this; // ancestor
29101   this.z = 0; // prelim
29102   this.m = 0; // mod
29103   this.c = 0; // change
29104   this.s = 0; // shift
29105   this.t = null; // thread
29106   this.i = i; // number
29107 }
29108
29109 TreeNode.prototype = Object.create(Node.prototype);
29110
29111 function treeRoot(root) {
29112   var tree = new TreeNode(root, 0),
29113       node,
29114       nodes = [tree],
29115       child,
29116       children,
29117       i,
29118       n;
29119
29120   while (node = nodes.pop()) {
29121     if (children = node._.children) {
29122       node.children = new Array(n = children.length);
29123       for (i = n - 1; i >= 0; --i) {
29124         nodes.push(child = node.children[i] = new TreeNode(children[i], i));
29125         child.parent = node;
29126       }
29127     }
29128   }
29129
29130   (tree.parent = new TreeNode(null, 0)).children = [tree];
29131   return tree;
29132 }
29133
29134 // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
29135 var tree = function() {
29136   var separation = defaultSeparation$1,
29137       dx = 1,
29138       dy = 1,
29139       nodeSize = null;
29140
29141   function tree(root) {
29142     var t = treeRoot(root);
29143
29144     // Compute the layout using Buchheim et al.’s algorithm.
29145     t.eachAfter(firstWalk), t.parent.m = -t.z;
29146     t.eachBefore(secondWalk);
29147
29148     // If a fixed node size is specified, scale x and y.
29149     if (nodeSize) root.eachBefore(sizeNode);
29150
29151     // If a fixed tree size is specified, scale x and y based on the extent.
29152     // Compute the left-most, right-most, and depth-most nodes for extents.
29153     else {
29154       var left = root,
29155           right = root,
29156           bottom = root;
29157       root.eachBefore(function(node) {
29158         if (node.x < left.x) left = node;
29159         if (node.x > right.x) right = node;
29160         if (node.depth > bottom.depth) bottom = node;
29161       });
29162       var s = left === right ? 1 : separation(left, right) / 2,
29163           tx = s - left.x,
29164           kx = dx / (right.x + s + tx),
29165           ky = dy / (bottom.depth || 1);
29166       root.eachBefore(function(node) {
29167         node.x = (node.x + tx) * kx;
29168         node.y = node.depth * ky;
29169       });
29170     }
29171
29172     return root;
29173   }
29174
29175   // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
29176   // applied recursively to the children of v, as well as the function
29177   // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
29178   // node v is placed to the midpoint of its outermost children.
29179   function firstWalk(v) {
29180     var children = v.children,
29181         siblings = v.parent.children,
29182         w = v.i ? siblings[v.i - 1] : null;
29183     if (children) {
29184       executeShifts(v);
29185       var midpoint = (children[0].z + children[children.length - 1].z) / 2;
29186       if (w) {
29187         v.z = w.z + separation(v._, w._);
29188         v.m = v.z - midpoint;
29189       } else {
29190         v.z = midpoint;
29191       }
29192     } else if (w) {
29193       v.z = w.z + separation(v._, w._);
29194     }
29195     v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
29196   }
29197
29198   // Computes all real x-coordinates by summing up the modifiers recursively.
29199   function secondWalk(v) {
29200     v._.x = v.z + v.parent.m;
29201     v.m += v.parent.m;
29202   }
29203
29204   // The core of the algorithm. Here, a new subtree is combined with the
29205   // previous subtrees. Threads are used to traverse the inside and outside
29206   // contours of the left and right subtree up to the highest common level. The
29207   // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
29208   // superscript o means outside and i means inside, the subscript - means left
29209   // subtree and + means right subtree. For summing up the modifiers along the
29210   // contour, we use respective variables si+, si-, so-, and so+. Whenever two
29211   // nodes of the inside contours conflict, we compute the left one of the
29212   // greatest uncommon ancestors using the function ANCESTOR and call MOVE
29213   // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
29214   // Finally, we add a new thread (if necessary).
29215   function apportion(v, w, ancestor) {
29216     if (w) {
29217       var vip = v,
29218           vop = v,
29219           vim = w,
29220           vom = vip.parent.children[0],
29221           sip = vip.m,
29222           sop = vop.m,
29223           sim = vim.m,
29224           som = vom.m,
29225           shift;
29226       while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
29227         vom = nextLeft(vom);
29228         vop = nextRight(vop);
29229         vop.a = v;
29230         shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
29231         if (shift > 0) {
29232           moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
29233           sip += shift;
29234           sop += shift;
29235         }
29236         sim += vim.m;
29237         sip += vip.m;
29238         som += vom.m;
29239         sop += vop.m;
29240       }
29241       if (vim && !nextRight(vop)) {
29242         vop.t = vim;
29243         vop.m += sim - sop;
29244       }
29245       if (vip && !nextLeft(vom)) {
29246         vom.t = vip;
29247         vom.m += sip - som;
29248         ancestor = v;
29249       }
29250     }
29251     return ancestor;
29252   }
29253
29254   function sizeNode(node) {
29255     node.x *= dx;
29256     node.y = node.depth * dy;
29257   }
29258
29259   tree.separation = function(x) {
29260     return arguments.length ? (separation = x, tree) : separation;
29261   };
29262
29263   tree.size = function(x) {
29264     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
29265   };
29266
29267   tree.nodeSize = function(x) {
29268     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
29269   };
29270
29271   return tree;
29272 };
29273
29274 var treemapSlice = function(parent, x0, y0, x1, y1) {
29275   var nodes = parent.children,
29276       node,
29277       i = -1,
29278       n = nodes.length,
29279       k = parent.value && (y1 - y0) / parent.value;
29280
29281   while (++i < n) {
29282     node = nodes[i], node.x0 = x0, node.x1 = x1;
29283     node.y0 = y0, node.y1 = y0 += node.value * k;
29284   }
29285 };
29286
29287 var phi = (1 + Math.sqrt(5)) / 2;
29288
29289 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
29290   var rows = [],
29291       nodes = parent.children,
29292       row,
29293       nodeValue,
29294       i0 = 0,
29295       i1 = 0,
29296       n = nodes.length,
29297       dx, dy,
29298       value = parent.value,
29299       sumValue,
29300       minValue,
29301       maxValue,
29302       newRatio,
29303       minRatio,
29304       alpha,
29305       beta;
29306
29307   while (i0 < n) {
29308     dx = x1 - x0, dy = y1 - y0;
29309
29310     // Find the next non-empty node.
29311     do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
29312     minValue = maxValue = sumValue;
29313     alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
29314     beta = sumValue * sumValue * alpha;
29315     minRatio = Math.max(maxValue / beta, beta / minValue);
29316
29317     // Keep adding nodes while the aspect ratio maintains or improves.
29318     for (; i1 < n; ++i1) {
29319       sumValue += nodeValue = nodes[i1].value;
29320       if (nodeValue < minValue) minValue = nodeValue;
29321       if (nodeValue > maxValue) maxValue = nodeValue;
29322       beta = sumValue * sumValue * alpha;
29323       newRatio = Math.max(maxValue / beta, beta / minValue);
29324       if (newRatio > minRatio) { sumValue -= nodeValue; break; }
29325       minRatio = newRatio;
29326     }
29327
29328     // Position and record the row orientation.
29329     rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
29330     if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
29331     else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
29332     value -= sumValue, i0 = i1;
29333   }
29334
29335   return rows;
29336 }
29337
29338 var squarify = (function custom(ratio) {
29339
29340   function squarify(parent, x0, y0, x1, y1) {
29341     squarifyRatio(ratio, parent, x0, y0, x1, y1);
29342   }
29343
29344   squarify.ratio = function(x) {
29345     return custom((x = +x) > 1 ? x : 1);
29346   };
29347
29348   return squarify;
29349 })(phi);
29350
29351 var index$3 = function() {
29352   var tile = squarify,
29353       round = false,
29354       dx = 1,
29355       dy = 1,
29356       paddingStack = [0],
29357       paddingInner = constantZero,
29358       paddingTop = constantZero,
29359       paddingRight = constantZero,
29360       paddingBottom = constantZero,
29361       paddingLeft = constantZero;
29362
29363   function treemap(root) {
29364     root.x0 =
29365     root.y0 = 0;
29366     root.x1 = dx;
29367     root.y1 = dy;
29368     root.eachBefore(positionNode);
29369     paddingStack = [0];
29370     if (round) root.eachBefore(roundNode);
29371     return root;
29372   }
29373
29374   function positionNode(node) {
29375     var p = paddingStack[node.depth],
29376         x0 = node.x0 + p,
29377         y0 = node.y0 + p,
29378         x1 = node.x1 - p,
29379         y1 = node.y1 - p;
29380     if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29381     if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29382     node.x0 = x0;
29383     node.y0 = y0;
29384     node.x1 = x1;
29385     node.y1 = y1;
29386     if (node.children) {
29387       p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
29388       x0 += paddingLeft(node) - p;
29389       y0 += paddingTop(node) - p;
29390       x1 -= paddingRight(node) - p;
29391       y1 -= paddingBottom(node) - p;
29392       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29393       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29394       tile(node, x0, y0, x1, y1);
29395     }
29396   }
29397
29398   treemap.round = function(x) {
29399     return arguments.length ? (round = !!x, treemap) : round;
29400   };
29401
29402   treemap.size = function(x) {
29403     return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
29404   };
29405
29406   treemap.tile = function(x) {
29407     return arguments.length ? (tile = required(x), treemap) : tile;
29408   };
29409
29410   treemap.padding = function(x) {
29411     return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
29412   };
29413
29414   treemap.paddingInner = function(x) {
29415     return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$6(+x), treemap) : paddingInner;
29416   };
29417
29418   treemap.paddingOuter = function(x) {
29419     return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
29420   };
29421
29422   treemap.paddingTop = function(x) {
29423     return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$6(+x), treemap) : paddingTop;
29424   };
29425
29426   treemap.paddingRight = function(x) {
29427     return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$6(+x), treemap) : paddingRight;
29428   };
29429
29430   treemap.paddingBottom = function(x) {
29431     return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$6(+x), treemap) : paddingBottom;
29432   };
29433
29434   treemap.paddingLeft = function(x) {
29435     return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$6(+x), treemap) : paddingLeft;
29436   };
29437
29438   return treemap;
29439 };
29440
29441 var binary = function(parent, x0, y0, x1, y1) {
29442   var nodes = parent.children,
29443       i, n = nodes.length,
29444       sum, sums = new Array(n + 1);
29445
29446   for (sums[0] = sum = i = 0; i < n; ++i) {
29447     sums[i + 1] = sum += nodes[i].value;
29448   }
29449
29450   partition(0, n, parent.value, x0, y0, x1, y1);
29451
29452   function partition(i, j, value, x0, y0, x1, y1) {
29453     if (i >= j - 1) {
29454       var node = nodes[i];
29455       node.x0 = x0, node.y0 = y0;
29456       node.x1 = x1, node.y1 = y1;
29457       return;
29458     }
29459
29460     var valueOffset = sums[i],
29461         valueTarget = (value / 2) + valueOffset,
29462         k = i + 1,
29463         hi = j - 1;
29464
29465     while (k < hi) {
29466       var mid = k + hi >>> 1;
29467       if (sums[mid] < valueTarget) k = mid + 1;
29468       else hi = mid;
29469     }
29470
29471     var valueLeft = sums[k] - valueOffset,
29472         valueRight = value - valueLeft;
29473
29474     if ((y1 - y0) > (x1 - x0)) {
29475       var yk = (y0 * valueRight + y1 * valueLeft) / value;
29476       partition(i, k, valueLeft, x0, y0, x1, yk);
29477       partition(k, j, valueRight, x0, yk, x1, y1);
29478     } else {
29479       var xk = (x0 * valueRight + x1 * valueLeft) / value;
29480       partition(i, k, valueLeft, x0, y0, xk, y1);
29481       partition(k, j, valueRight, xk, y0, x1, y1);
29482     }
29483   }
29484 };
29485
29486 var sliceDice = function(parent, x0, y0, x1, y1) {
29487   (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
29488 };
29489
29490 var resquarify = (function custom(ratio) {
29491
29492   function resquarify(parent, x0, y0, x1, y1) {
29493     if ((rows = parent._squarify) && (rows.ratio === ratio)) {
29494       var rows,
29495           row,
29496           nodes,
29497           i,
29498           j = -1,
29499           n,
29500           m = rows.length,
29501           value = parent.value;
29502
29503       while (++j < m) {
29504         row = rows[j], nodes = row.children;
29505         for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
29506         if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
29507         else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
29508         value -= row.value;
29509       }
29510     } else {
29511       parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
29512       rows.ratio = ratio;
29513     }
29514   }
29515
29516   resquarify.ratio = function(x) {
29517     return custom((x = +x) > 1 ? x : 1);
29518   };
29519
29520   return resquarify;
29521 })(phi);
29522
29523 var center$1 = function(x, y) {
29524   var nodes;
29525
29526   if (x == null) x = 0;
29527   if (y == null) y = 0;
29528
29529   function force() {
29530     var i,
29531         n = nodes.length,
29532         node,
29533         sx = 0,
29534         sy = 0;
29535
29536     for (i = 0; i < n; ++i) {
29537       node = nodes[i], sx += node.x, sy += node.y;
29538     }
29539
29540     for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
29541       node = nodes[i], node.x -= sx, node.y -= sy;
29542     }
29543   }
29544
29545   force.initialize = function(_) {
29546     nodes = _;
29547   };
29548
29549   force.x = function(_) {
29550     return arguments.length ? (x = +_, force) : x;
29551   };
29552
29553   force.y = function(_) {
29554     return arguments.length ? (y = +_, force) : y;
29555   };
29556
29557   return force;
29558 };
29559
29560 var constant$7 = function(x) {
29561   return function() {
29562     return x;
29563   };
29564 };
29565
29566 var jiggle = function() {
29567   return (Math.random() - 0.5) * 1e-6;
29568 };
29569
29570 function x$1(d) {
29571   return d.x + d.vx;
29572 }
29573
29574 function y$1(d) {
29575   return d.y + d.vy;
29576 }
29577
29578 var collide = function(radius) {
29579   var nodes,
29580       radii,
29581       strength = 1,
29582       iterations = 1;
29583
29584   if (typeof radius !== "function") radius = constant$7(radius == null ? 1 : +radius);
29585
29586   function force() {
29587     var i, n = nodes.length,
29588         tree,
29589         node,
29590         xi,
29591         yi,
29592         ri,
29593         ri2;
29594
29595     for (var k = 0; k < iterations; ++k) {
29596       tree = quadtree(nodes, x$1, y$1).visitAfter(prepare);
29597       for (i = 0; i < n; ++i) {
29598         node = nodes[i];
29599         ri = radii[node.index], ri2 = ri * ri;
29600         xi = node.x + node.vx;
29601         yi = node.y + node.vy;
29602         tree.visit(apply);
29603       }
29604     }
29605
29606     function apply(quad, x0, y0, x1, y1) {
29607       var data = quad.data, rj = quad.r, r = ri + rj;
29608       if (data) {
29609         if (data.index > node.index) {
29610           var x = xi - data.x - data.vx,
29611               y = yi - data.y - data.vy,
29612               l = x * x + y * y;
29613           if (l < r * r) {
29614             if (x === 0) x = jiggle(), l += x * x;
29615             if (y === 0) y = jiggle(), l += y * y;
29616             l = (r - (l = Math.sqrt(l))) / l * strength;
29617             node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
29618             node.vy += (y *= l) * r;
29619             data.vx -= x * (r = 1 - r);
29620             data.vy -= y * r;
29621           }
29622         }
29623         return;
29624       }
29625       return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
29626     }
29627   }
29628
29629   function prepare(quad) {
29630     if (quad.data) return quad.r = radii[quad.data.index];
29631     for (var i = quad.r = 0; i < 4; ++i) {
29632       if (quad[i] && quad[i].r > quad.r) {
29633         quad.r = quad[i].r;
29634       }
29635     }
29636   }
29637
29638   function initialize() {
29639     if (!nodes) return;
29640     var i, n = nodes.length, node;
29641     radii = new Array(n);
29642     for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
29643   }
29644
29645   force.initialize = function(_) {
29646     nodes = _;
29647     initialize();
29648   };
29649
29650   force.iterations = function(_) {
29651     return arguments.length ? (iterations = +_, force) : iterations;
29652   };
29653
29654   force.strength = function(_) {
29655     return arguments.length ? (strength = +_, force) : strength;
29656   };
29657
29658   force.radius = function(_) {
29659     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : radius;
29660   };
29661
29662   return force;
29663 };
29664
29665 function index$4(d) {
29666   return d.index;
29667 }
29668
29669 function find(nodeById, nodeId) {
29670   var node = nodeById.get(nodeId);
29671   if (!node) throw new Error("missing: " + nodeId);
29672   return node;
29673 }
29674
29675 var link = function(links) {
29676   var id = index$4,
29677       strength = defaultStrength,
29678       strengths,
29679       distance = constant$7(30),
29680       distances,
29681       nodes,
29682       count,
29683       bias,
29684       iterations = 1;
29685
29686   if (links == null) links = [];
29687
29688   function defaultStrength(link) {
29689     return 1 / Math.min(count[link.source.index], count[link.target.index]);
29690   }
29691
29692   function force(alpha) {
29693     for (var k = 0, n = links.length; k < iterations; ++k) {
29694       for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
29695         link = links[i], source = link.source, target = link.target;
29696         x = target.x + target.vx - source.x - source.vx || jiggle();
29697         y = target.y + target.vy - source.y - source.vy || jiggle();
29698         l = Math.sqrt(x * x + y * y);
29699         l = (l - distances[i]) / l * alpha * strengths[i];
29700         x *= l, y *= l;
29701         target.vx -= x * (b = bias[i]);
29702         target.vy -= y * b;
29703         source.vx += x * (b = 1 - b);
29704         source.vy += y * b;
29705       }
29706     }
29707   }
29708
29709   function initialize() {
29710     if (!nodes) return;
29711
29712     var i,
29713         n = nodes.length,
29714         m = links.length,
29715         nodeById = map$1(nodes, id),
29716         link;
29717
29718     for (i = 0, count = new Array(n); i < m; ++i) {
29719       link = links[i], link.index = i;
29720       if (typeof link.source !== "object") link.source = find(nodeById, link.source);
29721       if (typeof link.target !== "object") link.target = find(nodeById, link.target);
29722       count[link.source.index] = (count[link.source.index] || 0) + 1;
29723       count[link.target.index] = (count[link.target.index] || 0) + 1;
29724     }
29725
29726     for (i = 0, bias = new Array(m); i < m; ++i) {
29727       link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
29728     }
29729
29730     strengths = new Array(m), initializeStrength();
29731     distances = new Array(m), initializeDistance();
29732   }
29733
29734   function initializeStrength() {
29735     if (!nodes) return;
29736
29737     for (var i = 0, n = links.length; i < n; ++i) {
29738       strengths[i] = +strength(links[i], i, links);
29739     }
29740   }
29741
29742   function initializeDistance() {
29743     if (!nodes) return;
29744
29745     for (var i = 0, n = links.length; i < n; ++i) {
29746       distances[i] = +distance(links[i], i, links);
29747     }
29748   }
29749
29750   force.initialize = function(_) {
29751     nodes = _;
29752     initialize();
29753   };
29754
29755   force.links = function(_) {
29756     return arguments.length ? (links = _, initialize(), force) : links;
29757   };
29758
29759   force.id = function(_) {
29760     return arguments.length ? (id = _, force) : id;
29761   };
29762
29763   force.iterations = function(_) {
29764     return arguments.length ? (iterations = +_, force) : iterations;
29765   };
29766
29767   force.strength = function(_) {
29768     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initializeStrength(), force) : strength;
29769   };
29770
29771   force.distance = function(_) {
29772     return arguments.length ? (distance = typeof _ === "function" ? _ : constant$7(+_), initializeDistance(), force) : distance;
29773   };
29774
29775   return force;
29776 };
29777
29778 function x$2(d) {
29779   return d.x;
29780 }
29781
29782 function y$2(d) {
29783   return d.y;
29784 }
29785
29786 var initialRadius = 10;
29787 var initialAngle = Math.PI * (3 - Math.sqrt(5));
29788
29789 var simulation = function(nodes) {
29790   var simulation,
29791       alpha = 1,
29792       alphaMin = 0.001,
29793       alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
29794       alphaTarget = 0,
29795       velocityDecay = 0.6,
29796       forces = map$1(),
29797       stepper = timer(step),
29798       event = dispatch("tick", "end");
29799
29800   if (nodes == null) nodes = [];
29801
29802   function step() {
29803     tick();
29804     event.call("tick", simulation);
29805     if (alpha < alphaMin) {
29806       stepper.stop();
29807       event.call("end", simulation);
29808     }
29809   }
29810
29811   function tick() {
29812     var i, n = nodes.length, node;
29813
29814     alpha += (alphaTarget - alpha) * alphaDecay;
29815
29816     forces.each(function(force) {
29817       force(alpha);
29818     });
29819
29820     for (i = 0; i < n; ++i) {
29821       node = nodes[i];
29822       if (node.fx == null) node.x += node.vx *= velocityDecay;
29823       else node.x = node.fx, node.vx = 0;
29824       if (node.fy == null) node.y += node.vy *= velocityDecay;
29825       else node.y = node.fy, node.vy = 0;
29826     }
29827   }
29828
29829   function initializeNodes() {
29830     for (var i = 0, n = nodes.length, node; i < n; ++i) {
29831       node = nodes[i], node.index = i;
29832       if (isNaN(node.x) || isNaN(node.y)) {
29833         var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
29834         node.x = radius * Math.cos(angle);
29835         node.y = radius * Math.sin(angle);
29836       }
29837       if (isNaN(node.vx) || isNaN(node.vy)) {
29838         node.vx = node.vy = 0;
29839       }
29840     }
29841   }
29842
29843   function initializeForce(force) {
29844     if (force.initialize) force.initialize(nodes);
29845     return force;
29846   }
29847
29848   initializeNodes();
29849
29850   return simulation = {
29851     tick: tick,
29852
29853     restart: function() {
29854       return stepper.restart(step), simulation;
29855     },
29856
29857     stop: function() {
29858       return stepper.stop(), simulation;
29859     },
29860
29861     nodes: function(_) {
29862       return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
29863     },
29864
29865     alpha: function(_) {
29866       return arguments.length ? (alpha = +_, simulation) : alpha;
29867     },
29868
29869     alphaMin: function(_) {
29870       return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
29871     },
29872
29873     alphaDecay: function(_) {
29874       return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
29875     },
29876
29877     alphaTarget: function(_) {
29878       return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
29879     },
29880
29881     velocityDecay: function(_) {
29882       return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
29883     },
29884
29885     force: function(name, _) {
29886       return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
29887     },
29888
29889     find: function(x, y, radius) {
29890       var i = 0,
29891           n = nodes.length,
29892           dx,
29893           dy,
29894           d2,
29895           node,
29896           closest;
29897
29898       if (radius == null) radius = Infinity;
29899       else radius *= radius;
29900
29901       for (i = 0; i < n; ++i) {
29902         node = nodes[i];
29903         dx = x - node.x;
29904         dy = y - node.y;
29905         d2 = dx * dx + dy * dy;
29906         if (d2 < radius) closest = node, radius = d2;
29907       }
29908
29909       return closest;
29910     },
29911
29912     on: function(name, _) {
29913       return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
29914     }
29915   };
29916 };
29917
29918 var manyBody = function() {
29919   var nodes,
29920       node,
29921       alpha,
29922       strength = constant$7(-30),
29923       strengths,
29924       distanceMin2 = 1,
29925       distanceMax2 = Infinity,
29926       theta2 = 0.81;
29927
29928   function force(_) {
29929     var i, n = nodes.length, tree = quadtree(nodes, x$2, y$2).visitAfter(accumulate);
29930     for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
29931   }
29932
29933   function initialize() {
29934     if (!nodes) return;
29935     var i, n = nodes.length, node;
29936     strengths = new Array(n);
29937     for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
29938   }
29939
29940   function accumulate(quad) {
29941     var strength = 0, q, c, x$$1, y$$1, i;
29942
29943     // For internal nodes, accumulate forces from child quadrants.
29944     if (quad.length) {
29945       for (x$$1 = y$$1 = i = 0; i < 4; ++i) {
29946         if ((q = quad[i]) && (c = q.value)) {
29947           strength += c, x$$1 += c * q.x, y$$1 += c * q.y;
29948         }
29949       }
29950       quad.x = x$$1 / strength;
29951       quad.y = y$$1 / strength;
29952     }
29953
29954     // For leaf nodes, accumulate forces from coincident quadrants.
29955     else {
29956       q = quad;
29957       q.x = q.data.x;
29958       q.y = q.data.y;
29959       do strength += strengths[q.data.index];
29960       while (q = q.next);
29961     }
29962
29963     quad.value = strength;
29964   }
29965
29966   function apply(quad, x1, _, x2) {
29967     if (!quad.value) return true;
29968
29969     var x$$1 = quad.x - node.x,
29970         y$$1 = quad.y - node.y,
29971         w = x2 - x1,
29972         l = x$$1 * x$$1 + y$$1 * y$$1;
29973
29974     // Apply the Barnes-Hut approximation if possible.
29975     // Limit forces for very close nodes; randomize direction if coincident.
29976     if (w * w / theta2 < l) {
29977       if (l < distanceMax2) {
29978         if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
29979         if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
29980         if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
29981         node.vx += x$$1 * quad.value * alpha / l;
29982         node.vy += y$$1 * quad.value * alpha / l;
29983       }
29984       return true;
29985     }
29986
29987     // Otherwise, process points directly.
29988     else if (quad.length || l >= distanceMax2) return;
29989
29990     // Limit forces for very close nodes; randomize direction if coincident.
29991     if (quad.data !== node || quad.next) {
29992       if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
29993       if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
29994       if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
29995     }
29996
29997     do if (quad.data !== node) {
29998       w = strengths[quad.data.index] * alpha / l;
29999       node.vx += x$$1 * w;
30000       node.vy += y$$1 * w;
30001     } while (quad = quad.next);
30002   }
30003
30004   force.initialize = function(_) {
30005     nodes = _;
30006     initialize();
30007   };
30008
30009   force.strength = function(_) {
30010     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30011   };
30012
30013   force.distanceMin = function(_) {
30014     return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
30015   };
30016
30017   force.distanceMax = function(_) {
30018     return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
30019   };
30020
30021   force.theta = function(_) {
30022     return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
30023   };
30024
30025   return force;
30026 };
30027
30028 var x$3 = function(x) {
30029   var strength = constant$7(0.1),
30030       nodes,
30031       strengths,
30032       xz;
30033
30034   if (typeof x !== "function") x = constant$7(x == null ? 0 : +x);
30035
30036   function force(alpha) {
30037     for (var i = 0, n = nodes.length, node; i < n; ++i) {
30038       node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
30039     }
30040   }
30041
30042   function initialize() {
30043     if (!nodes) return;
30044     var i, n = nodes.length;
30045     strengths = new Array(n);
30046     xz = new Array(n);
30047     for (i = 0; i < n; ++i) {
30048       strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
30049     }
30050   }
30051
30052   force.initialize = function(_) {
30053     nodes = _;
30054     initialize();
30055   };
30056
30057   force.strength = function(_) {
30058     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30059   };
30060
30061   force.x = function(_) {
30062     return arguments.length ? (x = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : x;
30063   };
30064
30065   return force;
30066 };
30067
30068 var y$3 = function(y) {
30069   var strength = constant$7(0.1),
30070       nodes,
30071       strengths,
30072       yz;
30073
30074   if (typeof y !== "function") y = constant$7(y == null ? 0 : +y);
30075
30076   function force(alpha) {
30077     for (var i = 0, n = nodes.length, node; i < n; ++i) {
30078       node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
30079     }
30080   }
30081
30082   function initialize() {
30083     if (!nodes) return;
30084     var i, n = nodes.length;
30085     strengths = new Array(n);
30086     yz = new Array(n);
30087     for (i = 0; i < n; ++i) {
30088       strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
30089     }
30090   }
30091
30092   force.initialize = function(_) {
30093     nodes = _;
30094     initialize();
30095   };
30096
30097   force.strength = function(_) {
30098     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30099   };
30100
30101   force.y = function(_) {
30102     return arguments.length ? (y = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : y;
30103   };
30104
30105   return force;
30106 };
30107
30108 function nopropagation() {
30109   event.stopImmediatePropagation();
30110 }
30111
30112 var noevent = function() {
30113   event.preventDefault();
30114   event.stopImmediatePropagation();
30115 };
30116
30117 var dragDisable = function(view) {
30118   var root = view.document.documentElement,
30119       selection$$1 = select(view).on("dragstart.drag", noevent, true);
30120   if ("onselectstart" in root) {
30121     selection$$1.on("selectstart.drag", noevent, true);
30122   } else {
30123     root.__noselect = root.style.MozUserSelect;
30124     root.style.MozUserSelect = "none";
30125   }
30126 };
30127
30128 function yesdrag(view, noclick) {
30129   var root = view.document.documentElement,
30130       selection$$1 = select(view).on("dragstart.drag", null);
30131   if (noclick) {
30132     selection$$1.on("click.drag", noevent, true);
30133     setTimeout(function() { selection$$1.on("click.drag", null); }, 0);
30134   }
30135   if ("onselectstart" in root) {
30136     selection$$1.on("selectstart.drag", null);
30137   } else {
30138     root.style.MozUserSelect = root.__noselect;
30139     delete root.__noselect;
30140   }
30141 }
30142
30143 var constant$8 = function(x) {
30144   return function() {
30145     return x;
30146   };
30147 };
30148
30149 function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
30150   this.target = target;
30151   this.type = type;
30152   this.subject = subject;
30153   this.identifier = id;
30154   this.active = active;
30155   this.x = x;
30156   this.y = y;
30157   this.dx = dx;
30158   this.dy = dy;
30159   this._ = dispatch;
30160 }
30161
30162 DragEvent.prototype.on = function() {
30163   var value = this._.on.apply(this._, arguments);
30164   return value === this._ ? this : value;
30165 };
30166
30167 // Ignore right-click, since that should open the context menu.
30168 function defaultFilter() {
30169   return !event.button;
30170 }
30171
30172 function defaultContainer() {
30173   return this.parentNode;
30174 }
30175
30176 function defaultSubject(d) {
30177   return d == null ? {x: event.x, y: event.y} : d;
30178 }
30179
30180 var drag = function() {
30181   var filter = defaultFilter,
30182       container = defaultContainer,
30183       subject = defaultSubject,
30184       gestures = {},
30185       listeners = dispatch("start", "drag", "end"),
30186       active = 0,
30187       mousemoving,
30188       touchending;
30189
30190   function drag(selection$$1) {
30191     selection$$1
30192         .on("mousedown.drag", mousedowned)
30193         .on("touchstart.drag", touchstarted)
30194         .on("touchmove.drag", touchmoved)
30195         .on("touchend.drag touchcancel.drag", touchended)
30196         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
30197   }
30198
30199   function mousedowned() {
30200     if (touchending || !filter.apply(this, arguments)) return;
30201     var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
30202     if (!gesture) return;
30203     select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
30204     dragDisable(event.view);
30205     nopropagation();
30206     mousemoving = false;
30207     gesture("start");
30208   }
30209
30210   function mousemoved() {
30211     noevent();
30212     mousemoving = true;
30213     gestures.mouse("drag");
30214   }
30215
30216   function mouseupped() {
30217     select(event.view).on("mousemove.drag mouseup.drag", null);
30218     yesdrag(event.view, mousemoving);
30219     noevent();
30220     gestures.mouse("end");
30221   }
30222
30223   function touchstarted() {
30224     if (!filter.apply(this, arguments)) return;
30225     var touches$$1 = event.changedTouches,
30226         c = container.apply(this, arguments),
30227         n = touches$$1.length, i, gesture;
30228
30229     for (i = 0; i < n; ++i) {
30230       if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) {
30231         nopropagation();
30232         gesture("start");
30233       }
30234     }
30235   }
30236
30237   function touchmoved() {
30238     var touches$$1 = event.changedTouches,
30239         n = touches$$1.length, i, gesture;
30240
30241     for (i = 0; i < n; ++i) {
30242       if (gesture = gestures[touches$$1[i].identifier]) {
30243         noevent();
30244         gesture("drag");
30245       }
30246     }
30247   }
30248
30249   function touchended() {
30250     var touches$$1 = event.changedTouches,
30251         n = touches$$1.length, i, gesture;
30252
30253     if (touchending) clearTimeout(touchending);
30254     touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
30255     for (i = 0; i < n; ++i) {
30256       if (gesture = gestures[touches$$1[i].identifier]) {
30257         nopropagation();
30258         gesture("end");
30259       }
30260     }
30261   }
30262
30263   function beforestart(id, container, point, that, args) {
30264     var p = point(container, id), s, dx, dy,
30265         sublisteners = listeners.copy();
30266
30267     if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
30268       if ((event.subject = s = subject.apply(that, args)) == null) return false;
30269       dx = s.x - p[0] || 0;
30270       dy = s.y - p[1] || 0;
30271       return true;
30272     })) return;
30273
30274     return function gesture(type) {
30275       var p0 = p, n;
30276       switch (type) {
30277         case "start": gestures[id] = gesture, n = active++; break;
30278         case "end": delete gestures[id], --active; // nobreak
30279         case "drag": p = point(container, id), n = active; break;
30280       }
30281       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]);
30282     };
30283   }
30284
30285   drag.filter = function(_) {
30286     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$8(!!_), drag) : filter;
30287   };
30288
30289   drag.container = function(_) {
30290     return arguments.length ? (container = typeof _ === "function" ? _ : constant$8(_), drag) : container;
30291   };
30292
30293   drag.subject = function(_) {
30294     return arguments.length ? (subject = typeof _ === "function" ? _ : constant$8(_), drag) : subject;
30295   };
30296
30297   drag.on = function() {
30298     var value = listeners.on.apply(listeners, arguments);
30299     return value === listeners ? drag : value;
30300   };
30301
30302   return drag;
30303 };
30304
30305 var constant$9 = function(x) {
30306   return function() {
30307     return x;
30308   };
30309 };
30310
30311 function x$4(d) {
30312   return d[0];
30313 }
30314
30315 function y$4(d) {
30316   return d[1];
30317 }
30318
30319 function RedBlackTree() {
30320   this._ = null; // root node
30321 }
30322
30323 function RedBlackNode(node) {
30324   node.U = // parent node
30325   node.C = // color - true for red, false for black
30326   node.L = // left node
30327   node.R = // right node
30328   node.P = // previous node
30329   node.N = null; // next node
30330 }
30331
30332 RedBlackTree.prototype = {
30333   constructor: RedBlackTree,
30334
30335   insert: function(after, node) {
30336     var parent, grandpa, uncle;
30337
30338     if (after) {
30339       node.P = after;
30340       node.N = after.N;
30341       if (after.N) after.N.P = node;
30342       after.N = node;
30343       if (after.R) {
30344         after = after.R;
30345         while (after.L) after = after.L;
30346         after.L = node;
30347       } else {
30348         after.R = node;
30349       }
30350       parent = after;
30351     } else if (this._) {
30352       after = RedBlackFirst(this._);
30353       node.P = null;
30354       node.N = after;
30355       after.P = after.L = node;
30356       parent = after;
30357     } else {
30358       node.P = node.N = null;
30359       this._ = node;
30360       parent = null;
30361     }
30362     node.L = node.R = null;
30363     node.U = parent;
30364     node.C = true;
30365
30366     after = node;
30367     while (parent && parent.C) {
30368       grandpa = parent.U;
30369       if (parent === grandpa.L) {
30370         uncle = grandpa.R;
30371         if (uncle && uncle.C) {
30372           parent.C = uncle.C = false;
30373           grandpa.C = true;
30374           after = grandpa;
30375         } else {
30376           if (after === parent.R) {
30377             RedBlackRotateLeft(this, parent);
30378             after = parent;
30379             parent = after.U;
30380           }
30381           parent.C = false;
30382           grandpa.C = true;
30383           RedBlackRotateRight(this, grandpa);
30384         }
30385       } else {
30386         uncle = grandpa.L;
30387         if (uncle && uncle.C) {
30388           parent.C = uncle.C = false;
30389           grandpa.C = true;
30390           after = grandpa;
30391         } else {
30392           if (after === parent.L) {
30393             RedBlackRotateRight(this, parent);
30394             after = parent;
30395             parent = after.U;
30396           }
30397           parent.C = false;
30398           grandpa.C = true;
30399           RedBlackRotateLeft(this, grandpa);
30400         }
30401       }
30402       parent = after.U;
30403     }
30404     this._.C = false;
30405   },
30406
30407   remove: function(node) {
30408     if (node.N) node.N.P = node.P;
30409     if (node.P) node.P.N = node.N;
30410     node.N = node.P = null;
30411
30412     var parent = node.U,
30413         sibling,
30414         left = node.L,
30415         right = node.R,
30416         next,
30417         red;
30418
30419     if (!left) next = right;
30420     else if (!right) next = left;
30421     else next = RedBlackFirst(right);
30422
30423     if (parent) {
30424       if (parent.L === node) parent.L = next;
30425       else parent.R = next;
30426     } else {
30427       this._ = next;
30428     }
30429
30430     if (left && right) {
30431       red = next.C;
30432       next.C = node.C;
30433       next.L = left;
30434       left.U = next;
30435       if (next !== right) {
30436         parent = next.U;
30437         next.U = node.U;
30438         node = next.R;
30439         parent.L = node;
30440         next.R = right;
30441         right.U = next;
30442       } else {
30443         next.U = parent;
30444         parent = next;
30445         node = next.R;
30446       }
30447     } else {
30448       red = node.C;
30449       node = next;
30450     }
30451
30452     if (node) node.U = parent;
30453     if (red) return;
30454     if (node && node.C) { node.C = false; return; }
30455
30456     do {
30457       if (node === this._) break;
30458       if (node === parent.L) {
30459         sibling = parent.R;
30460         if (sibling.C) {
30461           sibling.C = false;
30462           parent.C = true;
30463           RedBlackRotateLeft(this, parent);
30464           sibling = parent.R;
30465         }
30466         if ((sibling.L && sibling.L.C)
30467             || (sibling.R && sibling.R.C)) {
30468           if (!sibling.R || !sibling.R.C) {
30469             sibling.L.C = false;
30470             sibling.C = true;
30471             RedBlackRotateRight(this, sibling);
30472             sibling = parent.R;
30473           }
30474           sibling.C = parent.C;
30475           parent.C = sibling.R.C = false;
30476           RedBlackRotateLeft(this, parent);
30477           node = this._;
30478           break;
30479         }
30480       } else {
30481         sibling = parent.L;
30482         if (sibling.C) {
30483           sibling.C = false;
30484           parent.C = true;
30485           RedBlackRotateRight(this, parent);
30486           sibling = parent.L;
30487         }
30488         if ((sibling.L && sibling.L.C)
30489           || (sibling.R && sibling.R.C)) {
30490           if (!sibling.L || !sibling.L.C) {
30491             sibling.R.C = false;
30492             sibling.C = true;
30493             RedBlackRotateLeft(this, sibling);
30494             sibling = parent.L;
30495           }
30496           sibling.C = parent.C;
30497           parent.C = sibling.L.C = false;
30498           RedBlackRotateRight(this, parent);
30499           node = this._;
30500           break;
30501         }
30502       }
30503       sibling.C = true;
30504       node = parent;
30505       parent = parent.U;
30506     } while (!node.C);
30507
30508     if (node) node.C = false;
30509   }
30510 };
30511
30512 function RedBlackRotateLeft(tree, node) {
30513   var p = node,
30514       q = node.R,
30515       parent = p.U;
30516
30517   if (parent) {
30518     if (parent.L === p) parent.L = q;
30519     else parent.R = q;
30520   } else {
30521     tree._ = q;
30522   }
30523
30524   q.U = parent;
30525   p.U = q;
30526   p.R = q.L;
30527   if (p.R) p.R.U = p;
30528   q.L = p;
30529 }
30530
30531 function RedBlackRotateRight(tree, node) {
30532   var p = node,
30533       q = node.L,
30534       parent = p.U;
30535
30536   if (parent) {
30537     if (parent.L === p) parent.L = q;
30538     else parent.R = q;
30539   } else {
30540     tree._ = q;
30541   }
30542
30543   q.U = parent;
30544   p.U = q;
30545   p.L = q.R;
30546   if (p.L) p.L.U = p;
30547   q.R = p;
30548 }
30549
30550 function RedBlackFirst(node) {
30551   while (node.L) node = node.L;
30552   return node;
30553 }
30554
30555 function createEdge(left, right, v0, v1) {
30556   var edge = [null, null],
30557       index = edges.push(edge) - 1;
30558   edge.left = left;
30559   edge.right = right;
30560   if (v0) setEdgeEnd(edge, left, right, v0);
30561   if (v1) setEdgeEnd(edge, right, left, v1);
30562   cells[left.index].halfedges.push(index);
30563   cells[right.index].halfedges.push(index);
30564   return edge;
30565 }
30566
30567 function createBorderEdge(left, v0, v1) {
30568   var edge = [v0, v1];
30569   edge.left = left;
30570   return edge;
30571 }
30572
30573 function setEdgeEnd(edge, left, right, vertex) {
30574   if (!edge[0] && !edge[1]) {
30575     edge[0] = vertex;
30576     edge.left = left;
30577     edge.right = right;
30578   } else if (edge.left === right) {
30579     edge[1] = vertex;
30580   } else {
30581     edge[0] = vertex;
30582   }
30583 }
30584
30585 // Liang–Barsky line clipping.
30586 function clipEdge(edge, x0, y0, x1, y1) {
30587   var a = edge[0],
30588       b = edge[1],
30589       ax = a[0],
30590       ay = a[1],
30591       bx = b[0],
30592       by = b[1],
30593       t0 = 0,
30594       t1 = 1,
30595       dx = bx - ax,
30596       dy = by - ay,
30597       r;
30598
30599   r = x0 - ax;
30600   if (!dx && r > 0) return;
30601   r /= dx;
30602   if (dx < 0) {
30603     if (r < t0) return;
30604     if (r < t1) t1 = r;
30605   } else if (dx > 0) {
30606     if (r > t1) return;
30607     if (r > t0) t0 = r;
30608   }
30609
30610   r = x1 - ax;
30611   if (!dx && r < 0) return;
30612   r /= dx;
30613   if (dx < 0) {
30614     if (r > t1) return;
30615     if (r > t0) t0 = r;
30616   } else if (dx > 0) {
30617     if (r < t0) return;
30618     if (r < t1) t1 = r;
30619   }
30620
30621   r = y0 - ay;
30622   if (!dy && r > 0) return;
30623   r /= dy;
30624   if (dy < 0) {
30625     if (r < t0) return;
30626     if (r < t1) t1 = r;
30627   } else if (dy > 0) {
30628     if (r > t1) return;
30629     if (r > t0) t0 = r;
30630   }
30631
30632   r = y1 - ay;
30633   if (!dy && r < 0) return;
30634   r /= dy;
30635   if (dy < 0) {
30636     if (r > t1) return;
30637     if (r > t0) t0 = r;
30638   } else if (dy > 0) {
30639     if (r < t0) return;
30640     if (r < t1) t1 = r;
30641   }
30642
30643   if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
30644
30645   if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
30646   if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
30647   return true;
30648 }
30649
30650 function connectEdge(edge, x0, y0, x1, y1) {
30651   var v1 = edge[1];
30652   if (v1) return true;
30653
30654   var v0 = edge[0],
30655       left = edge.left,
30656       right = edge.right,
30657       lx = left[0],
30658       ly = left[1],
30659       rx = right[0],
30660       ry = right[1],
30661       fx = (lx + rx) / 2,
30662       fy = (ly + ry) / 2,
30663       fm,
30664       fb;
30665
30666   if (ry === ly) {
30667     if (fx < x0 || fx >= x1) return;
30668     if (lx > rx) {
30669       if (!v0) v0 = [fx, y0];
30670       else if (v0[1] >= y1) return;
30671       v1 = [fx, y1];
30672     } else {
30673       if (!v0) v0 = [fx, y1];
30674       else if (v0[1] < y0) return;
30675       v1 = [fx, y0];
30676     }
30677   } else {
30678     fm = (lx - rx) / (ry - ly);
30679     fb = fy - fm * fx;
30680     if (fm < -1 || fm > 1) {
30681       if (lx > rx) {
30682         if (!v0) v0 = [(y0 - fb) / fm, y0];
30683         else if (v0[1] >= y1) return;
30684         v1 = [(y1 - fb) / fm, y1];
30685       } else {
30686         if (!v0) v0 = [(y1 - fb) / fm, y1];
30687         else if (v0[1] < y0) return;
30688         v1 = [(y0 - fb) / fm, y0];
30689       }
30690     } else {
30691       if (ly < ry) {
30692         if (!v0) v0 = [x0, fm * x0 + fb];
30693         else if (v0[0] >= x1) return;
30694         v1 = [x1, fm * x1 + fb];
30695       } else {
30696         if (!v0) v0 = [x1, fm * x1 + fb];
30697         else if (v0[0] < x0) return;
30698         v1 = [x0, fm * x0 + fb];
30699       }
30700     }
30701   }
30702
30703   edge[0] = v0;
30704   edge[1] = v1;
30705   return true;
30706 }
30707
30708 function clipEdges(x0, y0, x1, y1) {
30709   var i = edges.length,
30710       edge;
30711
30712   while (i--) {
30713     if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
30714         || !clipEdge(edge, x0, y0, x1, y1)
30715         || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$3
30716             || Math.abs(edge[0][1] - edge[1][1]) > epsilon$3)) {
30717       delete edges[i];
30718     }
30719   }
30720 }
30721
30722 function createCell(site) {
30723   return cells[site.index] = {
30724     site: site,
30725     halfedges: []
30726   };
30727 }
30728
30729 function cellHalfedgeAngle(cell, edge) {
30730   var site = cell.site,
30731       va = edge.left,
30732       vb = edge.right;
30733   if (site === vb) vb = va, va = site;
30734   if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
30735   if (site === va) va = edge[1], vb = edge[0];
30736   else va = edge[0], vb = edge[1];
30737   return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
30738 }
30739
30740 function cellHalfedgeStart(cell, edge) {
30741   return edge[+(edge.left !== cell.site)];
30742 }
30743
30744 function cellHalfedgeEnd(cell, edge) {
30745   return edge[+(edge.left === cell.site)];
30746 }
30747
30748 function sortCellHalfedges() {
30749   for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
30750     if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
30751       var index = new Array(m),
30752           array = new Array(m);
30753       for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
30754       index.sort(function(i, j) { return array[j] - array[i]; });
30755       for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
30756       for (j = 0; j < m; ++j) halfedges[j] = array[j];
30757     }
30758   }
30759 }
30760
30761 function clipCells(x0, y0, x1, y1) {
30762   var nCells = cells.length,
30763       iCell,
30764       cell,
30765       site,
30766       iHalfedge,
30767       halfedges,
30768       nHalfedges,
30769       start,
30770       startX,
30771       startY,
30772       end,
30773       endX,
30774       endY,
30775       cover = true;
30776
30777   for (iCell = 0; iCell < nCells; ++iCell) {
30778     if (cell = cells[iCell]) {
30779       site = cell.site;
30780       halfedges = cell.halfedges;
30781       iHalfedge = halfedges.length;
30782
30783       // Remove any dangling clipped edges.
30784       while (iHalfedge--) {
30785         if (!edges[halfedges[iHalfedge]]) {
30786           halfedges.splice(iHalfedge, 1);
30787         }
30788       }
30789
30790       // Insert any border edges as necessary.
30791       iHalfedge = 0, nHalfedges = halfedges.length;
30792       while (iHalfedge < nHalfedges) {
30793         end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
30794         start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
30795         if (Math.abs(endX - startX) > epsilon$3 || Math.abs(endY - startY) > epsilon$3) {
30796           halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
30797               Math.abs(endX - x0) < epsilon$3 && y1 - endY > epsilon$3 ? [x0, Math.abs(startX - x0) < epsilon$3 ? startY : y1]
30798               : Math.abs(endY - y1) < epsilon$3 && x1 - endX > epsilon$3 ? [Math.abs(startY - y1) < epsilon$3 ? startX : x1, y1]
30799               : Math.abs(endX - x1) < epsilon$3 && endY - y0 > epsilon$3 ? [x1, Math.abs(startX - x1) < epsilon$3 ? startY : y0]
30800               : Math.abs(endY - y0) < epsilon$3 && endX - x0 > epsilon$3 ? [Math.abs(startY - y0) < epsilon$3 ? startX : x0, y0]
30801               : null)) - 1);
30802           ++nHalfedges;
30803         }
30804       }
30805
30806       if (nHalfedges) cover = false;
30807     }
30808   }
30809
30810   // If there weren’t any edges, have the closest site cover the extent.
30811   // It doesn’t matter which corner of the extent we measure!
30812   if (cover) {
30813     var dx, dy, d2, dc = Infinity;
30814
30815     for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
30816       if (cell = cells[iCell]) {
30817         site = cell.site;
30818         dx = site[0] - x0;
30819         dy = site[1] - y0;
30820         d2 = dx * dx + dy * dy;
30821         if (d2 < dc) dc = d2, cover = cell;
30822       }
30823     }
30824
30825     if (cover) {
30826       var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
30827       cover.halfedges.push(
30828         edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
30829         edges.push(createBorderEdge(site, v01, v11)) - 1,
30830         edges.push(createBorderEdge(site, v11, v10)) - 1,
30831         edges.push(createBorderEdge(site, v10, v00)) - 1
30832       );
30833     }
30834   }
30835
30836   // Lastly delete any cells with no edges; these were entirely clipped.
30837   for (iCell = 0; iCell < nCells; ++iCell) {
30838     if (cell = cells[iCell]) {
30839       if (!cell.halfedges.length) {
30840         delete cells[iCell];
30841       }
30842     }
30843   }
30844 }
30845
30846 var circlePool = [];
30847
30848 var firstCircle;
30849
30850 function Circle() {
30851   RedBlackNode(this);
30852   this.x =
30853   this.y =
30854   this.arc =
30855   this.site =
30856   this.cy = null;
30857 }
30858
30859 function attachCircle(arc) {
30860   var lArc = arc.P,
30861       rArc = arc.N;
30862
30863   if (!lArc || !rArc) return;
30864
30865   var lSite = lArc.site,
30866       cSite = arc.site,
30867       rSite = rArc.site;
30868
30869   if (lSite === rSite) return;
30870
30871   var bx = cSite[0],
30872       by = cSite[1],
30873       ax = lSite[0] - bx,
30874       ay = lSite[1] - by,
30875       cx = rSite[0] - bx,
30876       cy = rSite[1] - by;
30877
30878   var d = 2 * (ax * cy - ay * cx);
30879   if (d >= -epsilon2$1) return;
30880
30881   var ha = ax * ax + ay * ay,
30882       hc = cx * cx + cy * cy,
30883       x = (cy * ha - ay * hc) / d,
30884       y = (ax * hc - cx * ha) / d;
30885
30886   var circle = circlePool.pop() || new Circle;
30887   circle.arc = arc;
30888   circle.site = cSite;
30889   circle.x = x + bx;
30890   circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
30891
30892   arc.circle = circle;
30893
30894   var before = null,
30895       node = circles._;
30896
30897   while (node) {
30898     if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
30899       if (node.L) node = node.L;
30900       else { before = node.P; break; }
30901     } else {
30902       if (node.R) node = node.R;
30903       else { before = node; break; }
30904     }
30905   }
30906
30907   circles.insert(before, circle);
30908   if (!before) firstCircle = circle;
30909 }
30910
30911 function detachCircle(arc) {
30912   var circle = arc.circle;
30913   if (circle) {
30914     if (!circle.P) firstCircle = circle.N;
30915     circles.remove(circle);
30916     circlePool.push(circle);
30917     RedBlackNode(circle);
30918     arc.circle = null;
30919   }
30920 }
30921
30922 var beachPool = [];
30923
30924 function Beach() {
30925   RedBlackNode(this);
30926   this.edge =
30927   this.site =
30928   this.circle = null;
30929 }
30930
30931 function createBeach(site) {
30932   var beach = beachPool.pop() || new Beach;
30933   beach.site = site;
30934   return beach;
30935 }
30936
30937 function detachBeach(beach) {
30938   detachCircle(beach);
30939   beaches.remove(beach);
30940   beachPool.push(beach);
30941   RedBlackNode(beach);
30942 }
30943
30944 function removeBeach(beach) {
30945   var circle = beach.circle,
30946       x = circle.x,
30947       y = circle.cy,
30948       vertex = [x, y],
30949       previous = beach.P,
30950       next = beach.N,
30951       disappearing = [beach];
30952
30953   detachBeach(beach);
30954
30955   var lArc = previous;
30956   while (lArc.circle
30957       && Math.abs(x - lArc.circle.x) < epsilon$3
30958       && Math.abs(y - lArc.circle.cy) < epsilon$3) {
30959     previous = lArc.P;
30960     disappearing.unshift(lArc);
30961     detachBeach(lArc);
30962     lArc = previous;
30963   }
30964
30965   disappearing.unshift(lArc);
30966   detachCircle(lArc);
30967
30968   var rArc = next;
30969   while (rArc.circle
30970       && Math.abs(x - rArc.circle.x) < epsilon$3
30971       && Math.abs(y - rArc.circle.cy) < epsilon$3) {
30972     next = rArc.N;
30973     disappearing.push(rArc);
30974     detachBeach(rArc);
30975     rArc = next;
30976   }
30977
30978   disappearing.push(rArc);
30979   detachCircle(rArc);
30980
30981   var nArcs = disappearing.length,
30982       iArc;
30983   for (iArc = 1; iArc < nArcs; ++iArc) {
30984     rArc = disappearing[iArc];
30985     lArc = disappearing[iArc - 1];
30986     setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
30987   }
30988
30989   lArc = disappearing[0];
30990   rArc = disappearing[nArcs - 1];
30991   rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
30992
30993   attachCircle(lArc);
30994   attachCircle(rArc);
30995 }
30996
30997 function addBeach(site) {
30998   var x = site[0],
30999       directrix = site[1],
31000       lArc,
31001       rArc,
31002       dxl,
31003       dxr,
31004       node = beaches._;
31005
31006   while (node) {
31007     dxl = leftBreakPoint(node, directrix) - x;
31008     if (dxl > epsilon$3) node = node.L; else {
31009       dxr = x - rightBreakPoint(node, directrix);
31010       if (dxr > epsilon$3) {
31011         if (!node.R) {
31012           lArc = node;
31013           break;
31014         }
31015         node = node.R;
31016       } else {
31017         if (dxl > -epsilon$3) {
31018           lArc = node.P;
31019           rArc = node;
31020         } else if (dxr > -epsilon$3) {
31021           lArc = node;
31022           rArc = node.N;
31023         } else {
31024           lArc = rArc = node;
31025         }
31026         break;
31027       }
31028     }
31029   }
31030
31031   createCell(site);
31032   var newArc = createBeach(site);
31033   beaches.insert(lArc, newArc);
31034
31035   if (!lArc && !rArc) return;
31036
31037   if (lArc === rArc) {
31038     detachCircle(lArc);
31039     rArc = createBeach(lArc.site);
31040     beaches.insert(newArc, rArc);
31041     newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
31042     attachCircle(lArc);
31043     attachCircle(rArc);
31044     return;
31045   }
31046
31047   if (!rArc) { // && lArc
31048     newArc.edge = createEdge(lArc.site, newArc.site);
31049     return;
31050   }
31051
31052   // else lArc !== rArc
31053   detachCircle(lArc);
31054   detachCircle(rArc);
31055
31056   var lSite = lArc.site,
31057       ax = lSite[0],
31058       ay = lSite[1],
31059       bx = site[0] - ax,
31060       by = site[1] - ay,
31061       rSite = rArc.site,
31062       cx = rSite[0] - ax,
31063       cy = rSite[1] - ay,
31064       d = 2 * (bx * cy - by * cx),
31065       hb = bx * bx + by * by,
31066       hc = cx * cx + cy * cy,
31067       vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
31068
31069   setEdgeEnd(rArc.edge, lSite, rSite, vertex);
31070   newArc.edge = createEdge(lSite, site, null, vertex);
31071   rArc.edge = createEdge(site, rSite, null, vertex);
31072   attachCircle(lArc);
31073   attachCircle(rArc);
31074 }
31075
31076 function leftBreakPoint(arc, directrix) {
31077   var site = arc.site,
31078       rfocx = site[0],
31079       rfocy = site[1],
31080       pby2 = rfocy - directrix;
31081
31082   if (!pby2) return rfocx;
31083
31084   var lArc = arc.P;
31085   if (!lArc) return -Infinity;
31086
31087   site = lArc.site;
31088   var lfocx = site[0],
31089       lfocy = site[1],
31090       plby2 = lfocy - directrix;
31091
31092   if (!plby2) return lfocx;
31093
31094   var hl = lfocx - rfocx,
31095       aby2 = 1 / pby2 - 1 / plby2,
31096       b = hl / plby2;
31097
31098   if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
31099
31100   return (rfocx + lfocx) / 2;
31101 }
31102
31103 function rightBreakPoint(arc, directrix) {
31104   var rArc = arc.N;
31105   if (rArc) return leftBreakPoint(rArc, directrix);
31106   var site = arc.site;
31107   return site[1] === directrix ? site[0] : Infinity;
31108 }
31109
31110 var epsilon$3 = 1e-6;
31111 var epsilon2$1 = 1e-12;
31112 var beaches;
31113 var cells;
31114 var circles;
31115 var edges;
31116
31117 function triangleArea(a, b, c) {
31118   return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
31119 }
31120
31121 function lexicographic(a, b) {
31122   return b[1] - a[1]
31123       || b[0] - a[0];
31124 }
31125
31126 function Diagram(sites, extent) {
31127   var site = sites.sort(lexicographic).pop(),
31128       x,
31129       y,
31130       circle;
31131
31132   edges = [];
31133   cells = new Array(sites.length);
31134   beaches = new RedBlackTree;
31135   circles = new RedBlackTree;
31136
31137   while (true) {
31138     circle = firstCircle;
31139     if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
31140       if (site[0] !== x || site[1] !== y) {
31141         addBeach(site);
31142         x = site[0], y = site[1];
31143       }
31144       site = sites.pop();
31145     } else if (circle) {
31146       removeBeach(circle.arc);
31147     } else {
31148       break;
31149     }
31150   }
31151
31152   sortCellHalfedges();
31153
31154   if (extent) {
31155     var x0 = +extent[0][0],
31156         y0 = +extent[0][1],
31157         x1 = +extent[1][0],
31158         y1 = +extent[1][1];
31159     clipEdges(x0, y0, x1, y1);
31160     clipCells(x0, y0, x1, y1);
31161   }
31162
31163   this.edges = edges;
31164   this.cells = cells;
31165
31166   beaches =
31167   circles =
31168   edges =
31169   cells = null;
31170 }
31171
31172 Diagram.prototype = {
31173   constructor: Diagram,
31174
31175   polygons: function() {
31176     var edges = this.edges;
31177
31178     return this.cells.map(function(cell) {
31179       var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
31180       polygon.data = cell.site.data;
31181       return polygon;
31182     });
31183   },
31184
31185   triangles: function() {
31186     var triangles = [],
31187         edges = this.edges;
31188
31189     this.cells.forEach(function(cell, i) {
31190       var site = cell.site,
31191           halfedges = cell.halfedges,
31192           j = -1,
31193           m = halfedges.length,
31194           s0,
31195           e1 = edges[halfedges[m - 1]],
31196           s1 = e1.left === site ? e1.right : e1.left;
31197
31198       while (++j < m) {
31199         s0 = s1;
31200         e1 = edges[halfedges[j]];
31201         s1 = e1.left === site ? e1.right : e1.left;
31202         if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
31203           triangles.push([site.data, s0.data, s1.data]);
31204         }
31205       }
31206     });
31207
31208     return triangles;
31209   },
31210
31211   links: function() {
31212     return this.edges.filter(function(edge) {
31213       return edge.right;
31214     }).map(function(edge) {
31215       return {
31216         source: edge.left.data,
31217         target: edge.right.data
31218       };
31219     });
31220   },
31221
31222   find: function(x, y, radius) {
31223     var that = this,
31224         i0, i1 = that._found || 0,
31225         cell = that.cells[i1] || that.cells[i1 = 0],
31226         dx = x - cell.site[0],
31227         dy = y - cell.site[1],
31228         d2 = dx * dx + dy * dy;
31229
31230     do {
31231       cell = that.cells[i0 = i1], i1 = null;
31232       cell.halfedges.forEach(function(e) {
31233         var edge = that.edges[e], v = edge.left;
31234         if ((v === cell.site || !v) && !(v = edge.right)) return;
31235         var vx = x - v[0],
31236             vy = y - v[1],
31237             v2 = vx * vx + vy * vy;
31238         if (v2 < d2) d2 = v2, i1 = v.index;
31239       });
31240     } while (i1 !== null);
31241
31242     that._found = i0;
31243
31244     return radius == null || d2 <= radius * radius ? cell.site : null;
31245   }
31246 };
31247
31248 var voronoi = function() {
31249   var x$$1 = x$4,
31250       y$$1 = y$4,
31251       extent = null;
31252
31253   function voronoi(data) {
31254     return new Diagram(data.map(function(d, i) {
31255       var s = [Math.round(x$$1(d, i, data) / epsilon$3) * epsilon$3, Math.round(y$$1(d, i, data) / epsilon$3) * epsilon$3];
31256       s.index = i;
31257       s.data = d;
31258       return s;
31259     }), extent);
31260   }
31261
31262   voronoi.polygons = function(data) {
31263     return voronoi(data).polygons();
31264   };
31265
31266   voronoi.links = function(data) {
31267     return voronoi(data).links();
31268   };
31269
31270   voronoi.triangles = function(data) {
31271     return voronoi(data).triangles();
31272   };
31273
31274   voronoi.x = function(_) {
31275     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : x$$1;
31276   };
31277
31278   voronoi.y = function(_) {
31279     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : y$$1;
31280   };
31281
31282   voronoi.extent = function(_) {
31283     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]]];
31284   };
31285
31286   voronoi.size = function(_) {
31287     return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
31288   };
31289
31290   return voronoi;
31291 };
31292
31293 var constant$10 = function(x) {
31294   return function() {
31295     return x;
31296   };
31297 };
31298
31299 function ZoomEvent(target, type, transform) {
31300   this.target = target;
31301   this.type = type;
31302   this.transform = transform;
31303 }
31304
31305 function Transform(k, x, y) {
31306   this.k = k;
31307   this.x = x;
31308   this.y = y;
31309 }
31310
31311 Transform.prototype = {
31312   constructor: Transform,
31313   scale: function(k) {
31314     return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
31315   },
31316   translate: function(x, y) {
31317     return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
31318   },
31319   apply: function(point) {
31320     return [point[0] * this.k + this.x, point[1] * this.k + this.y];
31321   },
31322   applyX: function(x) {
31323     return x * this.k + this.x;
31324   },
31325   applyY: function(y) {
31326     return y * this.k + this.y;
31327   },
31328   invert: function(location) {
31329     return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
31330   },
31331   invertX: function(x) {
31332     return (x - this.x) / this.k;
31333   },
31334   invertY: function(y) {
31335     return (y - this.y) / this.k;
31336   },
31337   rescaleX: function(x) {
31338     return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
31339   },
31340   rescaleY: function(y) {
31341     return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
31342   },
31343   toString: function() {
31344     return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
31345   }
31346 };
31347
31348 var identity$6 = new Transform(1, 0, 0);
31349
31350 transform.prototype = Transform.prototype;
31351
31352 function transform(node) {
31353   return node.__zoom || identity$6;
31354 }
31355
31356 function nopropagation$1() {
31357   event.stopImmediatePropagation();
31358 }
31359
31360 var noevent$1 = function() {
31361   event.preventDefault();
31362   event.stopImmediatePropagation();
31363 };
31364
31365 // Ignore right-click, since that should open the context menu.
31366 function defaultFilter$1() {
31367   return !event.button;
31368 }
31369
31370 function defaultExtent() {
31371   var e = this, w, h;
31372   if (e instanceof SVGElement) {
31373     e = e.ownerSVGElement || e;
31374     w = e.width.baseVal.value;
31375     h = e.height.baseVal.value;
31376   } else {
31377     w = e.clientWidth;
31378     h = e.clientHeight;
31379   }
31380   return [[0, 0], [w, h]];
31381 }
31382
31383 function defaultTransform() {
31384   return this.__zoom || identity$6;
31385 }
31386
31387 var zoom = function() {
31388   var filter = defaultFilter$1,
31389       extent = defaultExtent,
31390       k0 = 0,
31391       k1 = Infinity,
31392       x0 = -k1,
31393       x1 = k1,
31394       y0 = x0,
31395       y1 = x1,
31396       duration = 250,
31397       interpolate$$1 = interpolateZoom,
31398       gestures = [],
31399       listeners = dispatch("start", "zoom", "end"),
31400       touchstarting,
31401       touchending,
31402       touchDelay = 500,
31403       wheelDelay = 150;
31404
31405   function zoom(selection$$1) {
31406     selection$$1
31407         .on("wheel.zoom", wheeled)
31408         .on("mousedown.zoom", mousedowned)
31409         .on("dblclick.zoom", dblclicked)
31410         .on("touchstart.zoom", touchstarted)
31411         .on("touchmove.zoom", touchmoved)
31412         .on("touchend.zoom touchcancel.zoom", touchended)
31413         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
31414         .property("__zoom", defaultTransform);
31415   }
31416
31417   zoom.transform = function(collection, transform) {
31418     var selection$$1 = collection.selection ? collection.selection() : collection;
31419     selection$$1.property("__zoom", defaultTransform);
31420     if (collection !== selection$$1) {
31421       schedule(collection, transform);
31422     } else {
31423       selection$$1.interrupt().each(function() {
31424         gesture(this, arguments)
31425             .start()
31426             .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform)
31427             .end();
31428       });
31429     }
31430   };
31431
31432   zoom.scaleBy = function(selection$$1, k) {
31433     zoom.scaleTo(selection$$1, function() {
31434       var k0 = this.__zoom.k,
31435           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
31436       return k0 * k1;
31437     });
31438   };
31439
31440   zoom.scaleTo = function(selection$$1, k) {
31441     zoom.transform(selection$$1, function() {
31442       var e = extent.apply(this, arguments),
31443           t0 = this.__zoom,
31444           p0 = centroid(e),
31445           p1 = t0.invert(p0),
31446           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
31447       return constrain(translate(scale(t0, k1), p0, p1), e);
31448     });
31449   };
31450
31451   zoom.translateBy = function(selection$$1, x, y) {
31452     zoom.transform(selection$$1, function() {
31453       return constrain(this.__zoom.translate(
31454         typeof x === "function" ? x.apply(this, arguments) : x,
31455         typeof y === "function" ? y.apply(this, arguments) : y
31456       ), extent.apply(this, arguments));
31457     });
31458   };
31459
31460   function scale(transform, k) {
31461     k = Math.max(k0, Math.min(k1, k));
31462     return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
31463   }
31464
31465   function translate(transform, p0, p1) {
31466     var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k;
31467     return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
31468   }
31469
31470   function constrain(transform, extent) {
31471     var dx0 = transform.invertX(extent[0][0]) - x0,
31472         dx1 = transform.invertX(extent[1][0]) - x1,
31473         dy0 = transform.invertY(extent[0][1]) - y0,
31474         dy1 = transform.invertY(extent[1][1]) - y1;
31475     return transform.translate(
31476       dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),
31477       dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)
31478     );
31479   }
31480
31481   function centroid(extent) {
31482     return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
31483   }
31484
31485   function schedule(transition$$1, transform, center) {
31486     transition$$1
31487         .on("start.zoom", function() { gesture(this, arguments).start(); })
31488         .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
31489         .tween("zoom", function() {
31490           var that = this,
31491               args = arguments,
31492               g = gesture(that, args),
31493               e = extent.apply(that, args),
31494               p = center || centroid(e),
31495               w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
31496               a = that.__zoom,
31497               b = typeof transform === "function" ? transform.apply(that, args) : transform,
31498               i = interpolate$$1(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
31499           return function(t) {
31500             if (t === 1) t = b; // Avoid rounding error on end.
31501             else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
31502             g.zoom(null, t);
31503           };
31504         });
31505   }
31506
31507   function gesture(that, args) {
31508     for (var i = 0, n = gestures.length, g; i < n; ++i) {
31509       if ((g = gestures[i]).that === that) {
31510         return g;
31511       }
31512     }
31513     return new Gesture(that, args);
31514   }
31515
31516   function Gesture(that, args) {
31517     this.that = that;
31518     this.args = args;
31519     this.index = -1;
31520     this.active = 0;
31521     this.extent = extent.apply(that, args);
31522   }
31523
31524   Gesture.prototype = {
31525     start: function() {
31526       if (++this.active === 1) {
31527         this.index = gestures.push(this) - 1;
31528         this.emit("start");
31529       }
31530       return this;
31531     },
31532     zoom: function(key, transform) {
31533       if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
31534       if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
31535       if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
31536       this.that.__zoom = transform;
31537       this.emit("zoom");
31538       return this;
31539     },
31540     end: function() {
31541       if (--this.active === 0) {
31542         gestures.splice(this.index, 1);
31543         this.index = -1;
31544         this.emit("end");
31545       }
31546       return this;
31547     },
31548     emit: function(type) {
31549       customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
31550     }
31551   };
31552
31553   function wheeled() {
31554     if (!filter.apply(this, arguments)) return;
31555     var g = gesture(this, arguments),
31556         t = this.__zoom,
31557         k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))),
31558         p = mouse(this);
31559
31560     // If the mouse is in the same location as before, reuse it.
31561     // If there were recent wheel events, reset the wheel idle timeout.
31562     if (g.wheel) {
31563       if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
31564         g.mouse[1] = t.invert(g.mouse[0] = p);
31565       }
31566       clearTimeout(g.wheel);
31567     }
31568
31569     // If this wheel event won’t trigger a transform change, ignore it.
31570     else if (t.k === k) return;
31571
31572     // Otherwise, capture the mouse point and location at the start.
31573     else {
31574       g.mouse = [p, t.invert(p)];
31575       interrupt(this);
31576       g.start();
31577     }
31578
31579     noevent$1();
31580     g.wheel = setTimeout(wheelidled, wheelDelay);
31581     g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent));
31582
31583     function wheelidled() {
31584       g.wheel = null;
31585       g.end();
31586     }
31587   }
31588
31589   function mousedowned() {
31590     if (touchending || !filter.apply(this, arguments)) return;
31591     var g = gesture(this, arguments),
31592         v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
31593         p = mouse(this);
31594
31595     dragDisable(event.view);
31596     nopropagation$1();
31597     g.mouse = [p, this.__zoom.invert(p)];
31598     interrupt(this);
31599     g.start();
31600
31601     function mousemoved() {
31602       noevent$1();
31603       g.moved = true;
31604       g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent));
31605     }
31606
31607     function mouseupped() {
31608       v.on("mousemove.zoom mouseup.zoom", null);
31609       yesdrag(event.view, g.moved);
31610       noevent$1();
31611       g.end();
31612     }
31613   }
31614
31615   function dblclicked() {
31616     if (!filter.apply(this, arguments)) return;
31617     var t0 = this.__zoom,
31618         p0 = mouse(this),
31619         p1 = t0.invert(p0),
31620         k1 = t0.k * (event.shiftKey ? 0.5 : 2),
31621         t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments));
31622
31623     noevent$1();
31624     if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
31625     else select(this).call(zoom.transform, t1);
31626   }
31627
31628   function touchstarted() {
31629     if (!filter.apply(this, arguments)) return;
31630     var g = gesture(this, arguments),
31631         touches$$1 = event.changedTouches,
31632         n = touches$$1.length, i, t, p;
31633
31634     nopropagation$1();
31635     for (i = 0; i < n; ++i) {
31636       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
31637       p = [p, this.__zoom.invert(p), t.identifier];
31638       if (!g.touch0) g.touch0 = p;
31639       else if (!g.touch1) g.touch1 = p;
31640     }
31641
31642     // If this is a dbltap, reroute to the (optional) dblclick.zoom handler.
31643     if (touchstarting) {
31644       touchstarting = clearTimeout(touchstarting);
31645       if (!g.touch1) {
31646         g.end();
31647         p = select(this).on("dblclick.zoom");
31648         if (p) p.apply(this, arguments);
31649         return;
31650       }
31651     }
31652
31653     if (event.touches.length === n) {
31654       touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
31655       interrupt(this);
31656       g.start();
31657     }
31658   }
31659
31660   function touchmoved() {
31661     var g = gesture(this, arguments),
31662         touches$$1 = event.changedTouches,
31663         n = touches$$1.length, i, t, p, l;
31664
31665     noevent$1();
31666     if (touchstarting) touchstarting = clearTimeout(touchstarting);
31667     for (i = 0; i < n; ++i) {
31668       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
31669       if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
31670       else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
31671     }
31672     t = g.that.__zoom;
31673     if (g.touch1) {
31674       var p0 = g.touch0[0], l0 = g.touch0[1],
31675           p1 = g.touch1[0], l1 = g.touch1[1],
31676           dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
31677           dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
31678       t = scale(t, Math.sqrt(dp / dl));
31679       p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
31680       l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
31681     }
31682     else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
31683     else return;
31684     g.zoom("touch", constrain(translate(t, p, l), g.extent));
31685   }
31686
31687   function touchended() {
31688     var g = gesture(this, arguments),
31689         touches$$1 = event.changedTouches,
31690         n = touches$$1.length, i, t;
31691
31692     nopropagation$1();
31693     if (touchending) clearTimeout(touchending);
31694     touchending = setTimeout(function() { touchending = null; }, touchDelay);
31695     for (i = 0; i < n; ++i) {
31696       t = touches$$1[i];
31697       if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
31698       else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
31699     }
31700     if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
31701     if (!g.touch0) g.end();
31702   }
31703
31704   zoom.filter = function(_) {
31705     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$10(!!_), zoom) : filter;
31706   };
31707
31708   zoom.extent = function(_) {
31709     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$10([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
31710   };
31711
31712   zoom.scaleExtent = function(_) {
31713     return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1];
31714   };
31715
31716   zoom.translateExtent = function(_) {
31717     return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]];
31718   };
31719
31720   zoom.duration = function(_) {
31721     return arguments.length ? (duration = +_, zoom) : duration;
31722   };
31723
31724   zoom.interpolate = function(_) {
31725     return arguments.length ? (interpolate$$1 = _, zoom) : interpolate$$1;
31726   };
31727
31728   zoom.on = function() {
31729     var value = listeners.on.apply(listeners, arguments);
31730     return value === listeners ? zoom : value;
31731   };
31732
31733   return zoom;
31734 };
31735
31736 var constant$11 = function(x) {
31737   return function() {
31738     return x;
31739   };
31740 };
31741
31742 var BrushEvent = function(target, type, selection) {
31743   this.target = target;
31744   this.type = type;
31745   this.selection = selection;
31746 };
31747
31748 function nopropagation$2() {
31749   event.stopImmediatePropagation();
31750 }
31751
31752 var noevent$2 = function() {
31753   event.preventDefault();
31754   event.stopImmediatePropagation();
31755 };
31756
31757 var MODE_DRAG = {name: "drag"};
31758 var MODE_SPACE = {name: "space"};
31759 var MODE_HANDLE = {name: "handle"};
31760 var MODE_CENTER = {name: "center"};
31761
31762 var X = {
31763   name: "x",
31764   handles: ["e", "w"].map(type$3),
31765   input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
31766   output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
31767 };
31768
31769 var Y = {
31770   name: "y",
31771   handles: ["n", "s"].map(type$3),
31772   input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
31773   output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
31774 };
31775
31776 var XY = {
31777   name: "xy",
31778   handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$3),
31779   input: function(xy) { return xy; },
31780   output: function(xy) { return xy; }
31781 };
31782
31783 var cursors = {
31784   overlay: "crosshair",
31785   selection: "move",
31786   n: "ns-resize",
31787   e: "ew-resize",
31788   s: "ns-resize",
31789   w: "ew-resize",
31790   nw: "nwse-resize",
31791   ne: "nesw-resize",
31792   se: "nwse-resize",
31793   sw: "nesw-resize"
31794 };
31795
31796 var flipX = {
31797   e: "w",
31798   w: "e",
31799   nw: "ne",
31800   ne: "nw",
31801   se: "sw",
31802   sw: "se"
31803 };
31804
31805 var flipY = {
31806   n: "s",
31807   s: "n",
31808   nw: "sw",
31809   ne: "se",
31810   se: "ne",
31811   sw: "nw"
31812 };
31813
31814 var signsX = {
31815   overlay: +1,
31816   selection: +1,
31817   n: null,
31818   e: +1,
31819   s: null,
31820   w: -1,
31821   nw: -1,
31822   ne: +1,
31823   se: +1,
31824   sw: -1
31825 };
31826
31827 var signsY = {
31828   overlay: +1,
31829   selection: +1,
31830   n: -1,
31831   e: null,
31832   s: +1,
31833   w: null,
31834   nw: -1,
31835   ne: -1,
31836   se: +1,
31837   sw: +1
31838 };
31839
31840 function type$3(t) {
31841   return {type: t};
31842 }
31843
31844 // Ignore right-click, since that should open the context menu.
31845 function defaultFilter$2() {
31846   return !event.button;
31847 }
31848
31849 function defaultExtent$1() {
31850   var svg = this.ownerSVGElement || this;
31851   return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
31852 }
31853
31854 // Like d3.local, but with the name “__brush” rather than auto-generated.
31855 function local$1(node) {
31856   while (!node.__brush) if (!(node = node.parentNode)) return;
31857   return node.__brush;
31858 }
31859
31860 function empty$1(extent) {
31861   return extent[0][0] === extent[1][0]
31862       || extent[0][1] === extent[1][1];
31863 }
31864
31865 function brushSelection(node) {
31866   var state = node.__brush;
31867   return state ? state.dim.output(state.selection) : null;
31868 }
31869
31870 function brushX() {
31871   return brush$1(X);
31872 }
31873
31874 function brushY() {
31875   return brush$1(Y);
31876 }
31877
31878 var brush = function() {
31879   return brush$1(XY);
31880 };
31881
31882 function brush$1(dim) {
31883   var extent = defaultExtent$1,
31884       filter = defaultFilter$2,
31885       listeners = dispatch(brush, "start", "brush", "end"),
31886       handleSize = 6,
31887       touchending;
31888
31889   function brush(group) {
31890     var overlay = group
31891         .property("__brush", initialize)
31892       .selectAll(".overlay")
31893       .data([type$3("overlay")]);
31894
31895     overlay.enter().append("rect")
31896         .attr("class", "overlay")
31897         .attr("pointer-events", "all")
31898         .attr("cursor", cursors.overlay)
31899       .merge(overlay)
31900         .each(function() {
31901           var extent = local$1(this).extent;
31902           select(this)
31903               .attr("x", extent[0][0])
31904               .attr("y", extent[0][1])
31905               .attr("width", extent[1][0] - extent[0][0])
31906               .attr("height", extent[1][1] - extent[0][1]);
31907         });
31908
31909     group.selectAll(".selection")
31910       .data([type$3("selection")])
31911       .enter().append("rect")
31912         .attr("class", "selection")
31913         .attr("cursor", cursors.selection)
31914         .attr("fill", "#777")
31915         .attr("fill-opacity", 0.3)
31916         .attr("stroke", "#fff")
31917         .attr("shape-rendering", "crispEdges");
31918
31919     var handle = group.selectAll(".handle")
31920       .data(dim.handles, function(d) { return d.type; });
31921
31922     handle.exit().remove();
31923
31924     handle.enter().append("rect")
31925         .attr("class", function(d) { return "handle handle--" + d.type; })
31926         .attr("cursor", function(d) { return cursors[d.type]; });
31927
31928     group
31929         .each(redraw)
31930         .attr("fill", "none")
31931         .attr("pointer-events", "all")
31932         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
31933         .on("mousedown.brush touchstart.brush", started);
31934   }
31935
31936   brush.move = function(group, selection$$1) {
31937     if (group.selection) {
31938       group
31939           .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
31940           .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
31941           .tween("brush", function() {
31942             var that = this,
31943                 state = that.__brush,
31944                 emit = emitter(that, arguments),
31945                 selection0 = state.selection,
31946                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent),
31947                 i = interpolate(selection0, selection1);
31948
31949             function tween(t) {
31950               state.selection = t === 1 && empty$1(selection1) ? null : i(t);
31951               redraw.call(that);
31952               emit.brush();
31953             }
31954
31955             return selection0 && selection1 ? tween : tween(1);
31956           });
31957     } else {
31958       group
31959           .each(function() {
31960             var that = this,
31961                 args = arguments,
31962                 state = that.__brush,
31963                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent),
31964                 emit = emitter(that, args).beforestart();
31965
31966             interrupt(that);
31967             state.selection = selection1 == null || empty$1(selection1) ? null : selection1;
31968             redraw.call(that);
31969             emit.start().brush().end();
31970           });
31971     }
31972   };
31973
31974   function redraw() {
31975     var group = select(this),
31976         selection$$1 = local$1(this).selection;
31977
31978     if (selection$$1) {
31979       group.selectAll(".selection")
31980           .style("display", null)
31981           .attr("x", selection$$1[0][0])
31982           .attr("y", selection$$1[0][1])
31983           .attr("width", selection$$1[1][0] - selection$$1[0][0])
31984           .attr("height", selection$$1[1][1] - selection$$1[0][1]);
31985
31986       group.selectAll(".handle")
31987           .style("display", null)
31988           .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; })
31989           .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; })
31990           .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; })
31991           .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; });
31992     }
31993
31994     else {
31995       group.selectAll(".selection,.handle")
31996           .style("display", "none")
31997           .attr("x", null)
31998           .attr("y", null)
31999           .attr("width", null)
32000           .attr("height", null);
32001     }
32002   }
32003
32004   function emitter(that, args) {
32005     return that.__brush.emitter || new Emitter(that, args);
32006   }
32007
32008   function Emitter(that, args) {
32009     this.that = that;
32010     this.args = args;
32011     this.state = that.__brush;
32012     this.active = 0;
32013   }
32014
32015   Emitter.prototype = {
32016     beforestart: function() {
32017       if (++this.active === 1) this.state.emitter = this, this.starting = true;
32018       return this;
32019     },
32020     start: function() {
32021       if (this.starting) this.starting = false, this.emit("start");
32022       return this;
32023     },
32024     brush: function() {
32025       this.emit("brush");
32026       return this;
32027     },
32028     end: function() {
32029       if (--this.active === 0) delete this.state.emitter, this.emit("end");
32030       return this;
32031     },
32032     emit: function(type) {
32033       customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
32034     }
32035   };
32036
32037   function started() {
32038     if (event.touches) { if (event.changedTouches.length < event.touches.length) return noevent$2(); }
32039     else if (touchending) return;
32040     if (!filter.apply(this, arguments)) return;
32041
32042     var that = this,
32043         type = event.target.__data__.type,
32044         mode = (event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (event.altKey ? MODE_CENTER : MODE_HANDLE),
32045         signX = dim === Y ? null : signsX[type],
32046         signY = dim === X ? null : signsY[type],
32047         state = local$1(that),
32048         extent = state.extent,
32049         selection$$1 = state.selection,
32050         W = extent[0][0], w0, w1,
32051         N = extent[0][1], n0, n1,
32052         E = extent[1][0], e0, e1,
32053         S = extent[1][1], s0, s1,
32054         dx,
32055         dy,
32056         moving,
32057         shifting = signX && signY && event.shiftKey,
32058         lockX,
32059         lockY,
32060         point0 = mouse(that),
32061         point = point0,
32062         emit = emitter(that, arguments).beforestart();
32063
32064     if (type === "overlay") {
32065       state.selection = selection$$1 = [
32066         [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
32067         [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
32068       ];
32069     } else {
32070       w0 = selection$$1[0][0];
32071       n0 = selection$$1[0][1];
32072       e0 = selection$$1[1][0];
32073       s0 = selection$$1[1][1];
32074     }
32075
32076     w1 = w0;
32077     n1 = n0;
32078     e1 = e0;
32079     s1 = s0;
32080
32081     var group = select(that)
32082         .attr("pointer-events", "none");
32083
32084     var overlay = group.selectAll(".overlay")
32085         .attr("cursor", cursors[type]);
32086
32087     if (event.touches) {
32088       group
32089           .on("touchmove.brush", moved, true)
32090           .on("touchend.brush touchcancel.brush", ended, true);
32091     } else {
32092       var view = select(event.view)
32093           .on("keydown.brush", keydowned, true)
32094           .on("keyup.brush", keyupped, true)
32095           .on("mousemove.brush", moved, true)
32096           .on("mouseup.brush", ended, true);
32097
32098       dragDisable(event.view);
32099     }
32100
32101     nopropagation$2();
32102     interrupt(that);
32103     redraw.call(that);
32104     emit.start();
32105
32106     function moved() {
32107       var point1 = mouse(that);
32108       if (shifting && !lockX && !lockY) {
32109         if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
32110         else lockX = true;
32111       }
32112       point = point1;
32113       moving = true;
32114       noevent$2();
32115       move();
32116     }
32117
32118     function move() {
32119       var t;
32120
32121       dx = point[0] - point0[0];
32122       dy = point[1] - point0[1];
32123
32124       switch (mode) {
32125         case MODE_SPACE:
32126         case MODE_DRAG: {
32127           if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
32128           if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
32129           break;
32130         }
32131         case MODE_HANDLE: {
32132           if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
32133           else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
32134           if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
32135           else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
32136           break;
32137         }
32138         case MODE_CENTER: {
32139           if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
32140           if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
32141           break;
32142         }
32143       }
32144
32145       if (e1 < w1) {
32146         signX *= -1;
32147         t = w0, w0 = e0, e0 = t;
32148         t = w1, w1 = e1, e1 = t;
32149         if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
32150       }
32151
32152       if (s1 < n1) {
32153         signY *= -1;
32154         t = n0, n0 = s0, s0 = t;
32155         t = n1, n1 = s1, s1 = t;
32156         if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
32157       }
32158
32159       if (state.selection) selection$$1 = state.selection; // May be set by brush.move!
32160       if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0];
32161       if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1];
32162
32163       if (selection$$1[0][0] !== w1
32164           || selection$$1[0][1] !== n1
32165           || selection$$1[1][0] !== e1
32166           || selection$$1[1][1] !== s1) {
32167         state.selection = [[w1, n1], [e1, s1]];
32168         redraw.call(that);
32169         emit.brush();
32170       }
32171     }
32172
32173     function ended() {
32174       nopropagation$2();
32175       if (event.touches) {
32176         if (event.touches.length) return;
32177         if (touchending) clearTimeout(touchending);
32178         touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
32179         group.on("touchmove.brush touchend.brush touchcancel.brush", null);
32180       } else {
32181         yesdrag(event.view, moving);
32182         view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
32183       }
32184       group.attr("pointer-events", "all");
32185       overlay.attr("cursor", cursors.overlay);
32186       if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)!
32187       if (empty$1(selection$$1)) state.selection = null, redraw.call(that);
32188       emit.end();
32189     }
32190
32191     function keydowned() {
32192       switch (event.keyCode) {
32193         case 16: { // SHIFT
32194           shifting = signX && signY;
32195           break;
32196         }
32197         case 18: { // ALT
32198           if (mode === MODE_HANDLE) {
32199             if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
32200             if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
32201             mode = MODE_CENTER;
32202             move();
32203           }
32204           break;
32205         }
32206         case 32: { // SPACE; takes priority over ALT
32207           if (mode === MODE_HANDLE || mode === MODE_CENTER) {
32208             if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
32209             if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
32210             mode = MODE_SPACE;
32211             overlay.attr("cursor", cursors.selection);
32212             move();
32213           }
32214           break;
32215         }
32216         default: return;
32217       }
32218       noevent$2();
32219     }
32220
32221     function keyupped() {
32222       switch (event.keyCode) {
32223         case 16: { // SHIFT
32224           if (shifting) {
32225             lockX = lockY = shifting = false;
32226             move();
32227           }
32228           break;
32229         }
32230         case 18: { // ALT
32231           if (mode === MODE_CENTER) {
32232             if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
32233             if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
32234             mode = MODE_HANDLE;
32235             move();
32236           }
32237           break;
32238         }
32239         case 32: { // SPACE
32240           if (mode === MODE_SPACE) {
32241             if (event.altKey) {
32242               if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
32243               if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
32244               mode = MODE_CENTER;
32245             } else {
32246               if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
32247               if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
32248               mode = MODE_HANDLE;
32249             }
32250             overlay.attr("cursor", cursors[type]);
32251             move();
32252           }
32253           break;
32254         }
32255         default: return;
32256       }
32257       noevent$2();
32258     }
32259   }
32260
32261   function initialize() {
32262     var state = this.__brush || {selection: null};
32263     state.extent = extent.apply(this, arguments);
32264     state.dim = dim;
32265     return state;
32266   }
32267
32268   brush.extent = function(_) {
32269     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$11([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
32270   };
32271
32272   brush.filter = function(_) {
32273     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$11(!!_), brush) : filter;
32274   };
32275
32276   brush.handleSize = function(_) {
32277     return arguments.length ? (handleSize = +_, brush) : handleSize;
32278   };
32279
32280   brush.on = function() {
32281     var value = listeners.on.apply(listeners, arguments);
32282     return value === listeners ? brush : value;
32283   };
32284
32285   return brush;
32286 }
32287
32288 var cos = Math.cos;
32289 var sin = Math.sin;
32290 var pi$3 = Math.PI;
32291 var halfPi$2 = pi$3 / 2;
32292 var tau$3 = pi$3 * 2;
32293 var max$1 = Math.max;
32294
32295 function compareValue(compare) {
32296   return function(a, b) {
32297     return compare(
32298       a.source.value + a.target.value,
32299       b.source.value + b.target.value
32300     );
32301   };
32302 }
32303
32304 var chord = function() {
32305   var padAngle = 0,
32306       sortGroups = null,
32307       sortSubgroups = null,
32308       sortChords = null;
32309
32310   function chord(matrix) {
32311     var n = matrix.length,
32312         groupSums = [],
32313         groupIndex = range(n),
32314         subgroupIndex = [],
32315         chords = [],
32316         groups = chords.groups = new Array(n),
32317         subgroups = new Array(n * n),
32318         k,
32319         x,
32320         x0,
32321         dx,
32322         i,
32323         j;
32324
32325     // Compute the sum.
32326     k = 0, i = -1; while (++i < n) {
32327       x = 0, j = -1; while (++j < n) {
32328         x += matrix[i][j];
32329       }
32330       groupSums.push(x);
32331       subgroupIndex.push(range(n));
32332       k += x;
32333     }
32334
32335     // Sort groups…
32336     if (sortGroups) groupIndex.sort(function(a, b) {
32337       return sortGroups(groupSums[a], groupSums[b]);
32338     });
32339
32340     // Sort subgroups…
32341     if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
32342       d.sort(function(a, b) {
32343         return sortSubgroups(matrix[i][a], matrix[i][b]);
32344       });
32345     });
32346
32347     // Convert the sum to scaling factor for [0, 2pi].
32348     // TODO Allow start and end angle to be specified?
32349     // TODO Allow padding to be specified as percentage?
32350     k = max$1(0, tau$3 - padAngle * n) / k;
32351     dx = k ? padAngle : tau$3 / n;
32352
32353     // Compute the start and end angle for each group and subgroup.
32354     // Note: Opera has a bug reordering object literal properties!
32355     x = 0, i = -1; while (++i < n) {
32356       x0 = x, j = -1; while (++j < n) {
32357         var di = groupIndex[i],
32358             dj = subgroupIndex[di][j],
32359             v = matrix[di][dj],
32360             a0 = x,
32361             a1 = x += v * k;
32362         subgroups[dj * n + di] = {
32363           index: di,
32364           subindex: dj,
32365           startAngle: a0,
32366           endAngle: a1,
32367           value: v
32368         };
32369       }
32370       groups[di] = {
32371         index: di,
32372         startAngle: x0,
32373         endAngle: x,
32374         value: groupSums[di]
32375       };
32376       x += dx;
32377     }
32378
32379     // Generate chords for each (non-empty) subgroup-subgroup link.
32380     i = -1; while (++i < n) {
32381       j = i - 1; while (++j < n) {
32382         var source = subgroups[j * n + i],
32383             target = subgroups[i * n + j];
32384         if (source.value || target.value) {
32385           chords.push(source.value < target.value
32386               ? {source: target, target: source}
32387               : {source: source, target: target});
32388         }
32389       }
32390     }
32391
32392     return sortChords ? chords.sort(sortChords) : chords;
32393   }
32394
32395   chord.padAngle = function(_) {
32396     return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle;
32397   };
32398
32399   chord.sortGroups = function(_) {
32400     return arguments.length ? (sortGroups = _, chord) : sortGroups;
32401   };
32402
32403   chord.sortSubgroups = function(_) {
32404     return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
32405   };
32406
32407   chord.sortChords = function(_) {
32408     return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
32409   };
32410
32411   return chord;
32412 };
32413
32414 var slice$5 = Array.prototype.slice;
32415
32416 var constant$12 = function(x) {
32417   return function() {
32418     return x;
32419   };
32420 };
32421
32422 function defaultSource(d) {
32423   return d.source;
32424 }
32425
32426 function defaultTarget(d) {
32427   return d.target;
32428 }
32429
32430 function defaultRadius$1(d) {
32431   return d.radius;
32432 }
32433
32434 function defaultStartAngle(d) {
32435   return d.startAngle;
32436 }
32437
32438 function defaultEndAngle(d) {
32439   return d.endAngle;
32440 }
32441
32442 var ribbon = function() {
32443   var source = defaultSource,
32444       target = defaultTarget,
32445       radius = defaultRadius$1,
32446       startAngle = defaultStartAngle,
32447       endAngle = defaultEndAngle,
32448       context = null;
32449
32450   function ribbon() {
32451     var buffer,
32452         argv = slice$5.call(arguments),
32453         s = source.apply(this, argv),
32454         t = target.apply(this, argv),
32455         sr = +radius.apply(this, (argv[0] = s, argv)),
32456         sa0 = startAngle.apply(this, argv) - halfPi$2,
32457         sa1 = endAngle.apply(this, argv) - halfPi$2,
32458         sx0 = sr * cos(sa0),
32459         sy0 = sr * sin(sa0),
32460         tr = +radius.apply(this, (argv[0] = t, argv)),
32461         ta0 = startAngle.apply(this, argv) - halfPi$2,
32462         ta1 = endAngle.apply(this, argv) - halfPi$2;
32463
32464     if (!context) context = buffer = path();
32465
32466     context.moveTo(sx0, sy0);
32467     context.arc(0, 0, sr, sa0, sa1);
32468     if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
32469       context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
32470       context.arc(0, 0, tr, ta0, ta1);
32471     }
32472     context.quadraticCurveTo(0, 0, sx0, sy0);
32473     context.closePath();
32474
32475     if (buffer) return context = null, buffer + "" || null;
32476   }
32477
32478   ribbon.radius = function(_) {
32479     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$12(+_), ribbon) : radius;
32480   };
32481
32482   ribbon.startAngle = function(_) {
32483     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : startAngle;
32484   };
32485
32486   ribbon.endAngle = function(_) {
32487     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : endAngle;
32488   };
32489
32490   ribbon.source = function(_) {
32491     return arguments.length ? (source = _, ribbon) : source;
32492   };
32493
32494   ribbon.target = function(_) {
32495     return arguments.length ? (target = _, ribbon) : target;
32496   };
32497
32498   ribbon.context = function(_) {
32499     return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
32500   };
32501
32502   return ribbon;
32503 };
32504
32505 // Adds floating point numbers with twice the normal precision.
32506 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
32507 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
32508 // 305–363 (1997).
32509 // Code adapted from GeographicLib by Charles F. F. Karney,
32510 // http://geographiclib.sourceforge.net/
32511
32512 var adder = function() {
32513   return new Adder;
32514 };
32515
32516 function Adder() {
32517   this.reset();
32518 }
32519
32520 Adder.prototype = {
32521   constructor: Adder,
32522   reset: function() {
32523     this.s = // rounded value
32524     this.t = 0; // exact error
32525   },
32526   add: function(y) {
32527     add$1(temp, y, this.t);
32528     add$1(this, temp.s, this.s);
32529     if (this.s) this.t += temp.t;
32530     else this.s = temp.t;
32531   },
32532   valueOf: function() {
32533     return this.s;
32534   }
32535 };
32536
32537 var temp = new Adder;
32538
32539 function add$1(adder, a, b) {
32540   var x = adder.s = a + b,
32541       bv = x - a,
32542       av = x - bv;
32543   adder.t = (a - av) + (b - bv);
32544 }
32545
32546 var epsilon$4 = 1e-6;
32547 var epsilon2$2 = 1e-12;
32548 var pi$4 = Math.PI;
32549 var halfPi$3 = pi$4 / 2;
32550 var quarterPi = pi$4 / 4;
32551 var tau$4 = pi$4 * 2;
32552
32553 var degrees$1 = 180 / pi$4;
32554 var radians = pi$4 / 180;
32555
32556 var abs = Math.abs;
32557 var atan = Math.atan;
32558 var atan2 = Math.atan2;
32559 var cos$1 = Math.cos;
32560 var ceil = Math.ceil;
32561 var exp = Math.exp;
32562
32563 var log$1 = Math.log;
32564 var pow$1 = Math.pow;
32565 var sin$1 = Math.sin;
32566 var sign$1 = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
32567 var sqrt$1 = Math.sqrt;
32568 var tan = Math.tan;
32569
32570 function acos(x) {
32571   return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x);
32572 }
32573
32574 function asin$1(x) {
32575   return x > 1 ? halfPi$3 : x < -1 ? -halfPi$3 : Math.asin(x);
32576 }
32577
32578 function haversin(x) {
32579   return (x = sin$1(x / 2)) * x;
32580 }
32581
32582 function noop$2() {}
32583
32584 function streamGeometry(geometry, stream) {
32585   if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
32586     streamGeometryType[geometry.type](geometry, stream);
32587   }
32588 }
32589
32590 var streamObjectType = {
32591   Feature: function(feature, stream) {
32592     streamGeometry(feature.geometry, stream);
32593   },
32594   FeatureCollection: function(object, stream) {
32595     var features = object.features, i = -1, n = features.length;
32596     while (++i < n) streamGeometry(features[i].geometry, stream);
32597   }
32598 };
32599
32600 var streamGeometryType = {
32601   Sphere: function(object, stream) {
32602     stream.sphere();
32603   },
32604   Point: function(object, stream) {
32605     object = object.coordinates;
32606     stream.point(object[0], object[1], object[2]);
32607   },
32608   MultiPoint: function(object, stream) {
32609     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32610     while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
32611   },
32612   LineString: function(object, stream) {
32613     streamLine(object.coordinates, stream, 0);
32614   },
32615   MultiLineString: function(object, stream) {
32616     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32617     while (++i < n) streamLine(coordinates[i], stream, 0);
32618   },
32619   Polygon: function(object, stream) {
32620     streamPolygon(object.coordinates, stream);
32621   },
32622   MultiPolygon: function(object, stream) {
32623     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32624     while (++i < n) streamPolygon(coordinates[i], stream);
32625   },
32626   GeometryCollection: function(object, stream) {
32627     var geometries = object.geometries, i = -1, n = geometries.length;
32628     while (++i < n) streamGeometry(geometries[i], stream);
32629   }
32630 };
32631
32632 function streamLine(coordinates, stream, closed) {
32633   var i = -1, n = coordinates.length - closed, coordinate;
32634   stream.lineStart();
32635   while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
32636   stream.lineEnd();
32637 }
32638
32639 function streamPolygon(coordinates, stream) {
32640   var i = -1, n = coordinates.length;
32641   stream.polygonStart();
32642   while (++i < n) streamLine(coordinates[i], stream, 1);
32643   stream.polygonEnd();
32644 }
32645
32646 var geoStream = function(object, stream) {
32647   if (object && streamObjectType.hasOwnProperty(object.type)) {
32648     streamObjectType[object.type](object, stream);
32649   } else {
32650     streamGeometry(object, stream);
32651   }
32652 };
32653
32654 var areaRingSum = adder();
32655
32656 var areaSum = adder();
32657 var lambda00;
32658 var phi00;
32659 var lambda0;
32660 var cosPhi0;
32661 var sinPhi0;
32662
32663 var areaStream = {
32664   point: noop$2,
32665   lineStart: noop$2,
32666   lineEnd: noop$2,
32667   polygonStart: function() {
32668     areaRingSum.reset();
32669     areaStream.lineStart = areaRingStart;
32670     areaStream.lineEnd = areaRingEnd;
32671   },
32672   polygonEnd: function() {
32673     var areaRing = +areaRingSum;
32674     areaSum.add(areaRing < 0 ? tau$4 + areaRing : areaRing);
32675     this.lineStart = this.lineEnd = this.point = noop$2;
32676   },
32677   sphere: function() {
32678     areaSum.add(tau$4);
32679   }
32680 };
32681
32682 function areaRingStart() {
32683   areaStream.point = areaPointFirst;
32684 }
32685
32686 function areaRingEnd() {
32687   areaPoint(lambda00, phi00);
32688 }
32689
32690 function areaPointFirst(lambda, phi) {
32691   areaStream.point = areaPoint;
32692   lambda00 = lambda, phi00 = phi;
32693   lambda *= radians, phi *= radians;
32694   lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi);
32695 }
32696
32697 function areaPoint(lambda, phi) {
32698   lambda *= radians, phi *= radians;
32699   phi = phi / 2 + quarterPi; // half the angular distance from south pole
32700
32701   // Spherical excess E for a spherical triangle with vertices: south pole,
32702   // previous point, current point.  Uses a formula derived from Cagnoli’s
32703   // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
32704   var dLambda = lambda - lambda0,
32705       sdLambda = dLambda >= 0 ? 1 : -1,
32706       adLambda = sdLambda * dLambda,
32707       cosPhi = cos$1(phi),
32708       sinPhi = sin$1(phi),
32709       k = sinPhi0 * sinPhi,
32710       u = cosPhi0 * cosPhi + k * cos$1(adLambda),
32711       v = k * sdLambda * sin$1(adLambda);
32712   areaRingSum.add(atan2(v, u));
32713
32714   // Advance the previous points.
32715   lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
32716 }
32717
32718 var area$1 = function(object) {
32719   areaSum.reset();
32720   geoStream(object, areaStream);
32721   return areaSum * 2;
32722 };
32723
32724 function spherical(cartesian) {
32725   return [atan2(cartesian[1], cartesian[0]), asin$1(cartesian[2])];
32726 }
32727
32728 function cartesian(spherical) {
32729   var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi);
32730   return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)];
32731 }
32732
32733 function cartesianDot(a, b) {
32734   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
32735 }
32736
32737 function cartesianCross(a, b) {
32738   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]];
32739 }
32740
32741 // TODO return a
32742 function cartesianAddInPlace(a, b) {
32743   a[0] += b[0], a[1] += b[1], a[2] += b[2];
32744 }
32745
32746 function cartesianScale(vector, k) {
32747   return [vector[0] * k, vector[1] * k, vector[2] * k];
32748 }
32749
32750 // TODO return d
32751 function cartesianNormalizeInPlace(d) {
32752   var l = sqrt$1(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
32753   d[0] /= l, d[1] /= l, d[2] /= l;
32754 }
32755
32756 var lambda0$1;
32757 var phi0;
32758 var lambda1;
32759 var phi1;
32760 var lambda2;
32761 var lambda00$1;
32762 var phi00$1;
32763 var p0;
32764 var deltaSum = adder();
32765 var ranges;
32766 var range$1;
32767
32768 var boundsStream = {
32769   point: boundsPoint,
32770   lineStart: boundsLineStart,
32771   lineEnd: boundsLineEnd,
32772   polygonStart: function() {
32773     boundsStream.point = boundsRingPoint;
32774     boundsStream.lineStart = boundsRingStart;
32775     boundsStream.lineEnd = boundsRingEnd;
32776     deltaSum.reset();
32777     areaStream.polygonStart();
32778   },
32779   polygonEnd: function() {
32780     areaStream.polygonEnd();
32781     boundsStream.point = boundsPoint;
32782     boundsStream.lineStart = boundsLineStart;
32783     boundsStream.lineEnd = boundsLineEnd;
32784     if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
32785     else if (deltaSum > epsilon$4) phi1 = 90;
32786     else if (deltaSum < -epsilon$4) phi0 = -90;
32787     range$1[0] = lambda0$1, range$1[1] = lambda1;
32788   }
32789 };
32790
32791 function boundsPoint(lambda, phi) {
32792   ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]);
32793   if (phi < phi0) phi0 = phi;
32794   if (phi > phi1) phi1 = phi;
32795 }
32796
32797 function linePoint(lambda, phi) {
32798   var p = cartesian([lambda * radians, phi * radians]);
32799   if (p0) {
32800     var normal = cartesianCross(p0, p),
32801         equatorial = [normal[1], -normal[0], 0],
32802         inflection = cartesianCross(equatorial, normal);
32803     cartesianNormalizeInPlace(inflection);
32804     inflection = spherical(inflection);
32805     var delta = lambda - lambda2,
32806         sign$$1 = delta > 0 ? 1 : -1,
32807         lambdai = inflection[0] * degrees$1 * sign$$1,
32808         phii,
32809         antimeridian = abs(delta) > 180;
32810     if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
32811       phii = inflection[1] * degrees$1;
32812       if (phii > phi1) phi1 = phii;
32813     } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
32814       phii = -inflection[1] * degrees$1;
32815       if (phii < phi0) phi0 = phii;
32816     } else {
32817       if (phi < phi0) phi0 = phi;
32818       if (phi > phi1) phi1 = phi;
32819     }
32820     if (antimeridian) {
32821       if (lambda < lambda2) {
32822         if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
32823       } else {
32824         if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
32825       }
32826     } else {
32827       if (lambda1 >= lambda0$1) {
32828         if (lambda < lambda0$1) lambda0$1 = lambda;
32829         if (lambda > lambda1) lambda1 = lambda;
32830       } else {
32831         if (lambda > lambda2) {
32832           if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
32833         } else {
32834           if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
32835         }
32836       }
32837     }
32838   } else {
32839     boundsPoint(lambda, phi);
32840   }
32841   p0 = p, lambda2 = lambda;
32842 }
32843
32844 function boundsLineStart() {
32845   boundsStream.point = linePoint;
32846 }
32847
32848 function boundsLineEnd() {
32849   range$1[0] = lambda0$1, range$1[1] = lambda1;
32850   boundsStream.point = boundsPoint;
32851   p0 = null;
32852 }
32853
32854 function boundsRingPoint(lambda, phi) {
32855   if (p0) {
32856     var delta = lambda - lambda2;
32857     deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
32858   } else {
32859     lambda00$1 = lambda, phi00$1 = phi;
32860   }
32861   areaStream.point(lambda, phi);
32862   linePoint(lambda, phi);
32863 }
32864
32865 function boundsRingStart() {
32866   areaStream.lineStart();
32867 }
32868
32869 function boundsRingEnd() {
32870   boundsRingPoint(lambda00$1, phi00$1);
32871   areaStream.lineEnd();
32872   if (abs(deltaSum) > epsilon$4) lambda0$1 = -(lambda1 = 180);
32873   range$1[0] = lambda0$1, range$1[1] = lambda1;
32874   p0 = null;
32875 }
32876
32877 // Finds the left-right distance between two longitudes.
32878 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
32879 // the distance between ±180° to be 360°.
32880 function angle(lambda0, lambda1) {
32881   return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
32882 }
32883
32884 function rangeCompare(a, b) {
32885   return a[0] - b[0];
32886 }
32887
32888 function rangeContains(range, x) {
32889   return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
32890 }
32891
32892 var bounds = function(feature) {
32893   var i, n, a, b, merged, deltaMax, delta;
32894
32895   phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
32896   ranges = [];
32897   geoStream(feature, boundsStream);
32898
32899   // First, sort ranges by their minimum longitudes.
32900   if (n = ranges.length) {
32901     ranges.sort(rangeCompare);
32902
32903     // Then, merge any ranges that overlap.
32904     for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
32905       b = ranges[i];
32906       if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
32907         if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
32908         if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
32909       } else {
32910         merged.push(a = b);
32911       }
32912     }
32913
32914     // Finally, find the largest gap between the merged ranges.
32915     // The final bounding box will be the inverse of this gap.
32916     for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
32917       b = merged[i];
32918       if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
32919     }
32920   }
32921
32922   ranges = range$1 = null;
32923
32924   return lambda0$1 === Infinity || phi0 === Infinity
32925       ? [[NaN, NaN], [NaN, NaN]]
32926       : [[lambda0$1, phi0], [lambda1, phi1]];
32927 };
32928
32929 var W0;
32930 var W1;
32931 var X0;
32932 var Y0;
32933 var Z0;
32934 var X1;
32935 var Y1;
32936 var Z1;
32937 var X2;
32938 var Y2;
32939 var Z2;
32940 var lambda00$2;
32941 var phi00$2;
32942 var x0;
32943 var y0;
32944 var z0; // previous point
32945
32946 var centroidStream = {
32947   sphere: noop$2,
32948   point: centroidPoint,
32949   lineStart: centroidLineStart,
32950   lineEnd: centroidLineEnd,
32951   polygonStart: function() {
32952     centroidStream.lineStart = centroidRingStart;
32953     centroidStream.lineEnd = centroidRingEnd;
32954   },
32955   polygonEnd: function() {
32956     centroidStream.lineStart = centroidLineStart;
32957     centroidStream.lineEnd = centroidLineEnd;
32958   }
32959 };
32960
32961 // Arithmetic mean of Cartesian vectors.
32962 function centroidPoint(lambda, phi) {
32963   lambda *= radians, phi *= radians;
32964   var cosPhi = cos$1(phi);
32965   centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi));
32966 }
32967
32968 function centroidPointCartesian(x, y, z) {
32969   ++W0;
32970   X0 += (x - X0) / W0;
32971   Y0 += (y - Y0) / W0;
32972   Z0 += (z - Z0) / W0;
32973 }
32974
32975 function centroidLineStart() {
32976   centroidStream.point = centroidLinePointFirst;
32977 }
32978
32979 function centroidLinePointFirst(lambda, phi) {
32980   lambda *= radians, phi *= radians;
32981   var cosPhi = cos$1(phi);
32982   x0 = cosPhi * cos$1(lambda);
32983   y0 = cosPhi * sin$1(lambda);
32984   z0 = sin$1(phi);
32985   centroidStream.point = centroidLinePoint;
32986   centroidPointCartesian(x0, y0, z0);
32987 }
32988
32989 function centroidLinePoint(lambda, phi) {
32990   lambda *= radians, phi *= radians;
32991   var cosPhi = cos$1(phi),
32992       x = cosPhi * cos$1(lambda),
32993       y = cosPhi * sin$1(lambda),
32994       z = sin$1(phi),
32995       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);
32996   W1 += w;
32997   X1 += w * (x0 + (x0 = x));
32998   Y1 += w * (y0 + (y0 = y));
32999   Z1 += w * (z0 + (z0 = z));
33000   centroidPointCartesian(x0, y0, z0);
33001 }
33002
33003 function centroidLineEnd() {
33004   centroidStream.point = centroidPoint;
33005 }
33006
33007 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
33008 // J. Applied Mechanics 42, 239 (1975).
33009 function centroidRingStart() {
33010   centroidStream.point = centroidRingPointFirst;
33011 }
33012
33013 function centroidRingEnd() {
33014   centroidRingPoint(lambda00$2, phi00$2);
33015   centroidStream.point = centroidPoint;
33016 }
33017
33018 function centroidRingPointFirst(lambda, phi) {
33019   lambda00$2 = lambda, phi00$2 = phi;
33020   lambda *= radians, phi *= radians;
33021   centroidStream.point = centroidRingPoint;
33022   var cosPhi = cos$1(phi);
33023   x0 = cosPhi * cos$1(lambda);
33024   y0 = cosPhi * sin$1(lambda);
33025   z0 = sin$1(phi);
33026   centroidPointCartesian(x0, y0, z0);
33027 }
33028
33029 function centroidRingPoint(lambda, phi) {
33030   lambda *= radians, phi *= radians;
33031   var cosPhi = cos$1(phi),
33032       x = cosPhi * cos$1(lambda),
33033       y = cosPhi * sin$1(lambda),
33034       z = sin$1(phi),
33035       cx = y0 * z - z0 * y,
33036       cy = z0 * x - x0 * z,
33037       cz = x0 * y - y0 * x,
33038       m = sqrt$1(cx * cx + cy * cy + cz * cz),
33039       u = x0 * x + y0 * y + z0 * z,
33040       v = m && -acos(u) / m, // area weight
33041       w = atan2(m, u); // line weight
33042   X2 += v * cx;
33043   Y2 += v * cy;
33044   Z2 += v * cz;
33045   W1 += w;
33046   X1 += w * (x0 + (x0 = x));
33047   Y1 += w * (y0 + (y0 = y));
33048   Z1 += w * (z0 + (z0 = z));
33049   centroidPointCartesian(x0, y0, z0);
33050 }
33051
33052 var d3GeoCentroid = function(object) {
33053   W0 = W1 =
33054   X0 = Y0 = Z0 =
33055   X1 = Y1 = Z1 =
33056   X2 = Y2 = Z2 = 0;
33057   geoStream(object, centroidStream);
33058
33059   var x = X2,
33060       y = Y2,
33061       z = Z2,
33062       m = x * x + y * y + z * z;
33063
33064   // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
33065   if (m < epsilon2$2) {
33066     x = X1, y = Y1, z = Z1;
33067     // If the feature has zero length, fall back to arithmetic mean of point vectors.
33068     if (W1 < epsilon$4) x = X0, y = Y0, z = Z0;
33069     m = x * x + y * y + z * z;
33070     // If the feature still has an undefined ccentroid, then return.
33071     if (m < epsilon2$2) return [NaN, NaN];
33072   }
33073
33074   return [atan2(y, x) * degrees$1, asin$1(z / sqrt$1(m)) * degrees$1];
33075 };
33076
33077 var constant$13 = function(x) {
33078   return function() {
33079     return x;
33080   };
33081 };
33082
33083 var compose = function(a, b) {
33084
33085   function compose(x, y) {
33086     return x = a(x, y), b(x[0], x[1]);
33087   }
33088
33089   if (a.invert && b.invert) compose.invert = function(x, y) {
33090     return x = b.invert(x, y), x && a.invert(x[0], x[1]);
33091   };
33092
33093   return compose;
33094 };
33095
33096 function rotationIdentity(lambda, phi) {
33097   return [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi];
33098 }
33099
33100 rotationIdentity.invert = rotationIdentity;
33101
33102 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
33103   return (deltaLambda %= tau$4) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
33104     : rotationLambda(deltaLambda))
33105     : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
33106     : rotationIdentity);
33107 }
33108
33109 function forwardRotationLambda(deltaLambda) {
33110   return function(lambda, phi) {
33111     return lambda += deltaLambda, [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi];
33112   };
33113 }
33114
33115 function rotationLambda(deltaLambda) {
33116   var rotation = forwardRotationLambda(deltaLambda);
33117   rotation.invert = forwardRotationLambda(-deltaLambda);
33118   return rotation;
33119 }
33120
33121 function rotationPhiGamma(deltaPhi, deltaGamma) {
33122   var cosDeltaPhi = cos$1(deltaPhi),
33123       sinDeltaPhi = sin$1(deltaPhi),
33124       cosDeltaGamma = cos$1(deltaGamma),
33125       sinDeltaGamma = sin$1(deltaGamma);
33126
33127   function rotation(lambda, phi) {
33128     var cosPhi = cos$1(phi),
33129         x = cos$1(lambda) * cosPhi,
33130         y = sin$1(lambda) * cosPhi,
33131         z = sin$1(phi),
33132         k = z * cosDeltaPhi + x * sinDeltaPhi;
33133     return [
33134       atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
33135       asin$1(k * cosDeltaGamma + y * sinDeltaGamma)
33136     ];
33137   }
33138
33139   rotation.invert = function(lambda, phi) {
33140     var cosPhi = cos$1(phi),
33141         x = cos$1(lambda) * cosPhi,
33142         y = sin$1(lambda) * cosPhi,
33143         z = sin$1(phi),
33144         k = z * cosDeltaGamma - y * sinDeltaGamma;
33145     return [
33146       atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
33147       asin$1(k * cosDeltaPhi - x * sinDeltaPhi)
33148     ];
33149   };
33150
33151   return rotation;
33152 }
33153
33154 var rotation = function(rotate) {
33155   rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
33156
33157   function forward(coordinates) {
33158     coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
33159     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
33160   }
33161
33162   forward.invert = function(coordinates) {
33163     coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
33164     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
33165   };
33166
33167   return forward;
33168 };
33169
33170 // Generates a circle centered at [0°, 0°], with a given radius and precision.
33171 function circleStream(stream, radius, delta, direction, t0, t1) {
33172   if (!delta) return;
33173   var cosRadius = cos$1(radius),
33174       sinRadius = sin$1(radius),
33175       step = direction * delta;
33176   if (t0 == null) {
33177     t0 = radius + direction * tau$4;
33178     t1 = radius - step / 2;
33179   } else {
33180     t0 = circleRadius(cosRadius, t0);
33181     t1 = circleRadius(cosRadius, t1);
33182     if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$4;
33183   }
33184   for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
33185     point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]);
33186     stream.point(point[0], point[1]);
33187   }
33188 }
33189
33190 // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
33191 function circleRadius(cosRadius, point) {
33192   point = cartesian(point), point[0] -= cosRadius;
33193   cartesianNormalizeInPlace(point);
33194   var radius = acos(-point[1]);
33195   return ((-point[2] < 0 ? -radius : radius) + tau$4 - epsilon$4) % tau$4;
33196 }
33197
33198 var circle$1 = function() {
33199   var center = constant$13([0, 0]),
33200       radius = constant$13(90),
33201       precision = constant$13(6),
33202       ring,
33203       rotate,
33204       stream = {point: point};
33205
33206   function point(x, y) {
33207     ring.push(x = rotate(x, y));
33208     x[0] *= degrees$1, x[1] *= degrees$1;
33209   }
33210
33211   function circle() {
33212     var c = center.apply(this, arguments),
33213         r = radius.apply(this, arguments) * radians,
33214         p = precision.apply(this, arguments) * radians;
33215     ring = [];
33216     rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
33217     circleStream(stream, r, p, 1);
33218     c = {type: "Polygon", coordinates: [ring]};
33219     ring = rotate = null;
33220     return c;
33221   }
33222
33223   circle.center = function(_) {
33224     return arguments.length ? (center = typeof _ === "function" ? _ : constant$13([+_[0], +_[1]]), circle) : center;
33225   };
33226
33227   circle.radius = function(_) {
33228     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$13(+_), circle) : radius;
33229   };
33230
33231   circle.precision = function(_) {
33232     return arguments.length ? (precision = typeof _ === "function" ? _ : constant$13(+_), circle) : precision;
33233   };
33234
33235   return circle;
33236 };
33237
33238 var clipBuffer = function() {
33239   var lines = [],
33240       line;
33241   return {
33242     point: function(x, y) {
33243       line.push([x, y]);
33244     },
33245     lineStart: function() {
33246       lines.push(line = []);
33247     },
33248     lineEnd: noop$2,
33249     rejoin: function() {
33250       if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
33251     },
33252     result: function() {
33253       var result = lines;
33254       lines = [];
33255       line = null;
33256       return result;
33257     }
33258   };
33259 };
33260
33261 var clipLine = function(a, b, x0, y0, x1, y1) {
33262   var ax = a[0],
33263       ay = a[1],
33264       bx = b[0],
33265       by = b[1],
33266       t0 = 0,
33267       t1 = 1,
33268       dx = bx - ax,
33269       dy = by - ay,
33270       r;
33271
33272   r = x0 - ax;
33273   if (!dx && r > 0) return;
33274   r /= dx;
33275   if (dx < 0) {
33276     if (r < t0) return;
33277     if (r < t1) t1 = r;
33278   } else if (dx > 0) {
33279     if (r > t1) return;
33280     if (r > t0) t0 = r;
33281   }
33282
33283   r = x1 - ax;
33284   if (!dx && r < 0) return;
33285   r /= dx;
33286   if (dx < 0) {
33287     if (r > t1) return;
33288     if (r > t0) t0 = r;
33289   } else if (dx > 0) {
33290     if (r < t0) return;
33291     if (r < t1) t1 = r;
33292   }
33293
33294   r = y0 - ay;
33295   if (!dy && r > 0) return;
33296   r /= dy;
33297   if (dy < 0) {
33298     if (r < t0) return;
33299     if (r < t1) t1 = r;
33300   } else if (dy > 0) {
33301     if (r > t1) return;
33302     if (r > t0) t0 = r;
33303   }
33304
33305   r = y1 - ay;
33306   if (!dy && r < 0) return;
33307   r /= dy;
33308   if (dy < 0) {
33309     if (r > t1) return;
33310     if (r > t0) t0 = r;
33311   } else if (dy > 0) {
33312     if (r < t0) return;
33313     if (r < t1) t1 = r;
33314   }
33315
33316   if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
33317   if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
33318   return true;
33319 };
33320
33321 var pointEqual = function(a, b) {
33322   return abs(a[0] - b[0]) < epsilon$4 && abs(a[1] - b[1]) < epsilon$4;
33323 };
33324
33325 function Intersection(point, points, other, entry) {
33326   this.x = point;
33327   this.z = points;
33328   this.o = other; // another intersection
33329   this.e = entry; // is an entry?
33330   this.v = false; // visited
33331   this.n = this.p = null; // next & previous
33332 }
33333
33334 // A generalized polygon clipping algorithm: given a polygon that has been cut
33335 // into its visible line segments, and rejoins the segments by interpolating
33336 // along the clip edge.
33337 var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) {
33338   var subject = [],
33339       clip = [],
33340       i,
33341       n;
33342
33343   segments.forEach(function(segment) {
33344     if ((n = segment.length - 1) <= 0) return;
33345     var n, p0 = segment[0], p1 = segment[n], x;
33346
33347     // If the first and last points of a segment are coincident, then treat as a
33348     // closed ring. TODO if all rings are closed, then the winding order of the
33349     // exterior ring should be checked.
33350     if (pointEqual(p0, p1)) {
33351       stream.lineStart();
33352       for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
33353       stream.lineEnd();
33354       return;
33355     }
33356
33357     subject.push(x = new Intersection(p0, segment, null, true));
33358     clip.push(x.o = new Intersection(p0, null, x, false));
33359     subject.push(x = new Intersection(p1, segment, null, false));
33360     clip.push(x.o = new Intersection(p1, null, x, true));
33361   });
33362
33363   if (!subject.length) return;
33364
33365   clip.sort(compareIntersection);
33366   link$1(subject);
33367   link$1(clip);
33368
33369   for (i = 0, n = clip.length; i < n; ++i) {
33370     clip[i].e = startInside = !startInside;
33371   }
33372
33373   var start = subject[0],
33374       points,
33375       point;
33376
33377   while (1) {
33378     // Find first unvisited intersection.
33379     var current = start,
33380         isSubject = true;
33381     while (current.v) if ((current = current.n) === start) return;
33382     points = current.z;
33383     stream.lineStart();
33384     do {
33385       current.v = current.o.v = true;
33386       if (current.e) {
33387         if (isSubject) {
33388           for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
33389         } else {
33390           interpolate(current.x, current.n.x, 1, stream);
33391         }
33392         current = current.n;
33393       } else {
33394         if (isSubject) {
33395           points = current.p.z;
33396           for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
33397         } else {
33398           interpolate(current.x, current.p.x, -1, stream);
33399         }
33400         current = current.p;
33401       }
33402       current = current.o;
33403       points = current.z;
33404       isSubject = !isSubject;
33405     } while (!current.v);
33406     stream.lineEnd();
33407   }
33408 };
33409
33410 function link$1(array) {
33411   if (!(n = array.length)) return;
33412   var n,
33413       i = 0,
33414       a = array[0],
33415       b;
33416   while (++i < n) {
33417     a.n = b = array[i];
33418     b.p = a;
33419     a = b;
33420   }
33421   a.n = b = array[0];
33422   b.p = a;
33423 }
33424
33425 var clipMax = 1e9;
33426 var clipMin = -clipMax;
33427
33428 // TODO Use d3-polygon’s polygonContains here for the ring check?
33429 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
33430
33431 function clipExtent(x0, y0, x1, y1) {
33432
33433   function visible(x, y) {
33434     return x0 <= x && x <= x1 && y0 <= y && y <= y1;
33435   }
33436
33437   function interpolate(from, to, direction, stream) {
33438     var a = 0, a1 = 0;
33439     if (from == null
33440         || (a = corner(from, direction)) !== (a1 = corner(to, direction))
33441         || comparePoint(from, to) < 0 ^ direction > 0) {
33442       do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
33443       while ((a = (a + direction + 4) % 4) !== a1);
33444     } else {
33445       stream.point(to[0], to[1]);
33446     }
33447   }
33448
33449   function corner(p, direction) {
33450     return abs(p[0] - x0) < epsilon$4 ? direction > 0 ? 0 : 3
33451         : abs(p[0] - x1) < epsilon$4 ? direction > 0 ? 2 : 1
33452         : abs(p[1] - y0) < epsilon$4 ? direction > 0 ? 1 : 0
33453         : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
33454   }
33455
33456   function compareIntersection(a, b) {
33457     return comparePoint(a.x, b.x);
33458   }
33459
33460   function comparePoint(a, b) {
33461     var ca = corner(a, 1),
33462         cb = corner(b, 1);
33463     return ca !== cb ? ca - cb
33464         : ca === 0 ? b[1] - a[1]
33465         : ca === 1 ? a[0] - b[0]
33466         : ca === 2 ? a[1] - b[1]
33467         : b[0] - a[0];
33468   }
33469
33470   return function(stream) {
33471     var activeStream = stream,
33472         bufferStream = clipBuffer(),
33473         segments,
33474         polygon,
33475         ring,
33476         x__, y__, v__, // first point
33477         x_, y_, v_, // previous point
33478         first,
33479         clean;
33480
33481     var clipStream = {
33482       point: point,
33483       lineStart: lineStart,
33484       lineEnd: lineEnd,
33485       polygonStart: polygonStart,
33486       polygonEnd: polygonEnd
33487     };
33488
33489     function point(x, y) {
33490       if (visible(x, y)) activeStream.point(x, y);
33491     }
33492
33493     function polygonInside() {
33494       var winding = 0;
33495
33496       for (var i = 0, n = polygon.length; i < n; ++i) {
33497         for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
33498           a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
33499           if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
33500           else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
33501         }
33502       }
33503
33504       return winding;
33505     }
33506
33507     // Buffer geometry within a polygon and then clip it en masse.
33508     function polygonStart() {
33509       activeStream = bufferStream, segments = [], polygon = [], clean = true;
33510     }
33511
33512     function polygonEnd() {
33513       var startInside = polygonInside(),
33514           cleanInside = clean && startInside,
33515           visible = (segments = merge(segments)).length;
33516       if (cleanInside || visible) {
33517         stream.polygonStart();
33518         if (cleanInside) {
33519           stream.lineStart();
33520           interpolate(null, null, 1, stream);
33521           stream.lineEnd();
33522         }
33523         if (visible) {
33524           clipPolygon(segments, compareIntersection, startInside, interpolate, stream);
33525         }
33526         stream.polygonEnd();
33527       }
33528       activeStream = stream, segments = polygon = ring = null;
33529     }
33530
33531     function lineStart() {
33532       clipStream.point = linePoint;
33533       if (polygon) polygon.push(ring = []);
33534       first = true;
33535       v_ = false;
33536       x_ = y_ = NaN;
33537     }
33538
33539     // TODO rather than special-case polygons, simply handle them separately.
33540     // Ideally, coincident intersection points should be jittered to avoid
33541     // clipping issues.
33542     function lineEnd() {
33543       if (segments) {
33544         linePoint(x__, y__);
33545         if (v__ && v_) bufferStream.rejoin();
33546         segments.push(bufferStream.result());
33547       }
33548       clipStream.point = point;
33549       if (v_) activeStream.lineEnd();
33550     }
33551
33552     function linePoint(x, y) {
33553       var v = visible(x, y);
33554       if (polygon) ring.push([x, y]);
33555       if (first) {
33556         x__ = x, y__ = y, v__ = v;
33557         first = false;
33558         if (v) {
33559           activeStream.lineStart();
33560           activeStream.point(x, y);
33561         }
33562       } else {
33563         if (v && v_) activeStream.point(x, y);
33564         else {
33565           var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
33566               b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
33567           if (clipLine(a, b, x0, y0, x1, y1)) {
33568             if (!v_) {
33569               activeStream.lineStart();
33570               activeStream.point(a[0], a[1]);
33571             }
33572             activeStream.point(b[0], b[1]);
33573             if (!v) activeStream.lineEnd();
33574             clean = false;
33575           } else if (v) {
33576             activeStream.lineStart();
33577             activeStream.point(x, y);
33578             clean = false;
33579           }
33580         }
33581       }
33582       x_ = x, y_ = y, v_ = v;
33583     }
33584
33585     return clipStream;
33586   };
33587 }
33588
33589 var extent$1 = function() {
33590   var x0 = 0,
33591       y0 = 0,
33592       x1 = 960,
33593       y1 = 500,
33594       cache,
33595       cacheStream,
33596       clip;
33597
33598   return clip = {
33599     stream: function(stream) {
33600       return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream);
33601     },
33602     extent: function(_) {
33603       return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
33604     }
33605   };
33606 };
33607
33608 var lengthSum = adder();
33609 var lambda0$2;
33610 var sinPhi0$1;
33611 var cosPhi0$1;
33612
33613 var lengthStream = {
33614   sphere: noop$2,
33615   point: noop$2,
33616   lineStart: lengthLineStart,
33617   lineEnd: noop$2,
33618   polygonStart: noop$2,
33619   polygonEnd: noop$2
33620 };
33621
33622 function lengthLineStart() {
33623   lengthStream.point = lengthPointFirst;
33624   lengthStream.lineEnd = lengthLineEnd;
33625 }
33626
33627 function lengthLineEnd() {
33628   lengthStream.point = lengthStream.lineEnd = noop$2;
33629 }
33630
33631 function lengthPointFirst(lambda, phi) {
33632   lambda *= radians, phi *= radians;
33633   lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi);
33634   lengthStream.point = lengthPoint;
33635 }
33636
33637 function lengthPoint(lambda, phi) {
33638   lambda *= radians, phi *= radians;
33639   var sinPhi = sin$1(phi),
33640       cosPhi = cos$1(phi),
33641       delta = abs(lambda - lambda0$2),
33642       cosDelta = cos$1(delta),
33643       sinDelta = sin$1(delta),
33644       x = cosPhi * sinDelta,
33645       y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta,
33646       z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta;
33647   lengthSum.add(atan2(sqrt$1(x * x + y * y), z));
33648   lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi;
33649 }
33650
33651 var d3GeoLength = function(object) {
33652   lengthSum.reset();
33653   geoStream(object, lengthStream);
33654   return +lengthSum;
33655 };
33656
33657 var coordinates = [null, null];
33658 var object$1 = {type: "LineString", coordinates: coordinates};
33659
33660 var distance = function(a, b) {
33661   coordinates[0] = a;
33662   coordinates[1] = b;
33663   return d3GeoLength(object$1);
33664 };
33665
33666 function graticuleX(y0, y1, dy) {
33667   var y = range(y0, y1 - epsilon$4, dy).concat(y1);
33668   return function(x) { return y.map(function(y) { return [x, y]; }); };
33669 }
33670
33671 function graticuleY(x0, x1, dx) {
33672   var x = range(x0, x1 - epsilon$4, dx).concat(x1);
33673   return function(y) { return x.map(function(x) { return [x, y]; }); };
33674 }
33675
33676 function graticule() {
33677   var x1, x0, X1, X0,
33678       y1, y0, Y1, Y0,
33679       dx = 10, dy = dx, DX = 90, DY = 360,
33680       x, y, X, Y,
33681       precision = 2.5;
33682
33683   function graticule() {
33684     return {type: "MultiLineString", coordinates: lines()};
33685   }
33686
33687   function lines() {
33688     return range(ceil(X0 / DX) * DX, X1, DX).map(X)
33689         .concat(range(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
33690         .concat(range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$4; }).map(x))
33691         .concat(range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$4; }).map(y));
33692   }
33693
33694   graticule.lines = function() {
33695     return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
33696   };
33697
33698   graticule.outline = function() {
33699     return {
33700       type: "Polygon",
33701       coordinates: [
33702         X(X0).concat(
33703         Y(Y1).slice(1),
33704         X(X1).reverse().slice(1),
33705         Y(Y0).reverse().slice(1))
33706       ]
33707     };
33708   };
33709
33710   graticule.extent = function(_) {
33711     if (!arguments.length) return graticule.extentMinor();
33712     return graticule.extentMajor(_).extentMinor(_);
33713   };
33714
33715   graticule.extentMajor = function(_) {
33716     if (!arguments.length) return [[X0, Y0], [X1, Y1]];
33717     X0 = +_[0][0], X1 = +_[1][0];
33718     Y0 = +_[0][1], Y1 = +_[1][1];
33719     if (X0 > X1) _ = X0, X0 = X1, X1 = _;
33720     if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
33721     return graticule.precision(precision);
33722   };
33723
33724   graticule.extentMinor = function(_) {
33725     if (!arguments.length) return [[x0, y0], [x1, y1]];
33726     x0 = +_[0][0], x1 = +_[1][0];
33727     y0 = +_[0][1], y1 = +_[1][1];
33728     if (x0 > x1) _ = x0, x0 = x1, x1 = _;
33729     if (y0 > y1) _ = y0, y0 = y1, y1 = _;
33730     return graticule.precision(precision);
33731   };
33732
33733   graticule.step = function(_) {
33734     if (!arguments.length) return graticule.stepMinor();
33735     return graticule.stepMajor(_).stepMinor(_);
33736   };
33737
33738   graticule.stepMajor = function(_) {
33739     if (!arguments.length) return [DX, DY];
33740     DX = +_[0], DY = +_[1];
33741     return graticule;
33742   };
33743
33744   graticule.stepMinor = function(_) {
33745     if (!arguments.length) return [dx, dy];
33746     dx = +_[0], dy = +_[1];
33747     return graticule;
33748   };
33749
33750   graticule.precision = function(_) {
33751     if (!arguments.length) return precision;
33752     precision = +_;
33753     x = graticuleX(y0, y1, 90);
33754     y = graticuleY(x0, x1, precision);
33755     X = graticuleX(Y0, Y1, 90);
33756     Y = graticuleY(X0, X1, precision);
33757     return graticule;
33758   };
33759
33760   return graticule
33761       .extentMajor([[-180, -90 + epsilon$4], [180, 90 - epsilon$4]])
33762       .extentMinor([[-180, -80 - epsilon$4], [180, 80 + epsilon$4]]);
33763 }
33764
33765 function graticule10() {
33766   return graticule()();
33767 }
33768
33769 var interpolate$2 = function(a, b) {
33770   var x0 = a[0] * radians,
33771       y0 = a[1] * radians,
33772       x1 = b[0] * radians,
33773       y1 = b[1] * radians,
33774       cy0 = cos$1(y0),
33775       sy0 = sin$1(y0),
33776       cy1 = cos$1(y1),
33777       sy1 = sin$1(y1),
33778       kx0 = cy0 * cos$1(x0),
33779       ky0 = cy0 * sin$1(x0),
33780       kx1 = cy1 * cos$1(x1),
33781       ky1 = cy1 * sin$1(x1),
33782       d = 2 * asin$1(sqrt$1(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
33783       k = sin$1(d);
33784
33785   var interpolate = d ? function(t) {
33786     var B = sin$1(t *= d) / k,
33787         A = sin$1(d - t) / k,
33788         x = A * kx0 + B * kx1,
33789         y = A * ky0 + B * ky1,
33790         z = A * sy0 + B * sy1;
33791     return [
33792       atan2(y, x) * degrees$1,
33793       atan2(z, sqrt$1(x * x + y * y)) * degrees$1
33794     ];
33795   } : function() {
33796     return [x0 * degrees$1, y0 * degrees$1];
33797   };
33798
33799   interpolate.distance = d;
33800
33801   return interpolate;
33802 };
33803
33804 var identity$7 = function(x) {
33805   return x;
33806 };
33807
33808 var areaSum$1 = adder();
33809 var areaRingSum$1 = adder();
33810 var x00;
33811 var y00;
33812 var x0$1;
33813 var y0$1;
33814
33815 var areaStream$1 = {
33816   point: noop$2,
33817   lineStart: noop$2,
33818   lineEnd: noop$2,
33819   polygonStart: function() {
33820     areaStream$1.lineStart = areaRingStart$1;
33821     areaStream$1.lineEnd = areaRingEnd$1;
33822   },
33823   polygonEnd: function() {
33824     areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$2;
33825     areaSum$1.add(abs(areaRingSum$1));
33826     areaRingSum$1.reset();
33827   },
33828   result: function() {
33829     var area = areaSum$1 / 2;
33830     areaSum$1.reset();
33831     return area;
33832   }
33833 };
33834
33835 function areaRingStart$1() {
33836   areaStream$1.point = areaPointFirst$1;
33837 }
33838
33839 function areaPointFirst$1(x, y) {
33840   areaStream$1.point = areaPoint$1;
33841   x00 = x0$1 = x, y00 = y0$1 = y;
33842 }
33843
33844 function areaPoint$1(x, y) {
33845   areaRingSum$1.add(y0$1 * x - x0$1 * y);
33846   x0$1 = x, y0$1 = y;
33847 }
33848
33849 function areaRingEnd$1() {
33850   areaPoint$1(x00, y00);
33851 }
33852
33853 var x0$2 = Infinity;
33854 var y0$2 = x0$2;
33855 var x1 = -x0$2;
33856 var y1 = x1;
33857
33858 var boundsStream$1 = {
33859   point: boundsPoint$1,
33860   lineStart: noop$2,
33861   lineEnd: noop$2,
33862   polygonStart: noop$2,
33863   polygonEnd: noop$2,
33864   result: function() {
33865     var bounds = [[x0$2, y0$2], [x1, y1]];
33866     x1 = y1 = -(y0$2 = x0$2 = Infinity);
33867     return bounds;
33868   }
33869 };
33870
33871 function boundsPoint$1(x, y) {
33872   if (x < x0$2) x0$2 = x;
33873   if (x > x1) x1 = x;
33874   if (y < y0$2) y0$2 = y;
33875   if (y > y1) y1 = y;
33876 }
33877
33878 // TODO Enforce positive area for exterior, negative area for interior?
33879
33880 var X0$1 = 0;
33881 var Y0$1 = 0;
33882 var Z0$1 = 0;
33883 var X1$1 = 0;
33884 var Y1$1 = 0;
33885 var Z1$1 = 0;
33886 var X2$1 = 0;
33887 var Y2$1 = 0;
33888 var Z2$1 = 0;
33889 var x00$1;
33890 var y00$1;
33891 var x0$3;
33892 var y0$3;
33893
33894 var centroidStream$1 = {
33895   point: centroidPoint$1,
33896   lineStart: centroidLineStart$1,
33897   lineEnd: centroidLineEnd$1,
33898   polygonStart: function() {
33899     centroidStream$1.lineStart = centroidRingStart$1;
33900     centroidStream$1.lineEnd = centroidRingEnd$1;
33901   },
33902   polygonEnd: function() {
33903     centroidStream$1.point = centroidPoint$1;
33904     centroidStream$1.lineStart = centroidLineStart$1;
33905     centroidStream$1.lineEnd = centroidLineEnd$1;
33906   },
33907   result: function() {
33908     var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1]
33909         : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1]
33910         : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1]
33911         : [NaN, NaN];
33912     X0$1 = Y0$1 = Z0$1 =
33913     X1$1 = Y1$1 = Z1$1 =
33914     X2$1 = Y2$1 = Z2$1 = 0;
33915     return centroid;
33916   }
33917 };
33918
33919 function centroidPoint$1(x, y) {
33920   X0$1 += x;
33921   Y0$1 += y;
33922   ++Z0$1;
33923 }
33924
33925 function centroidLineStart$1() {
33926   centroidStream$1.point = centroidPointFirstLine;
33927 }
33928
33929 function centroidPointFirstLine(x, y) {
33930   centroidStream$1.point = centroidPointLine;
33931   centroidPoint$1(x0$3 = x, y0$3 = y);
33932 }
33933
33934 function centroidPointLine(x, y) {
33935   var dx = x - x0$3, dy = y - y0$3, z = sqrt$1(dx * dx + dy * dy);
33936   X1$1 += z * (x0$3 + x) / 2;
33937   Y1$1 += z * (y0$3 + y) / 2;
33938   Z1$1 += z;
33939   centroidPoint$1(x0$3 = x, y0$3 = y);
33940 }
33941
33942 function centroidLineEnd$1() {
33943   centroidStream$1.point = centroidPoint$1;
33944 }
33945
33946 function centroidRingStart$1() {
33947   centroidStream$1.point = centroidPointFirstRing;
33948 }
33949
33950 function centroidRingEnd$1() {
33951   centroidPointRing(x00$1, y00$1);
33952 }
33953
33954 function centroidPointFirstRing(x, y) {
33955   centroidStream$1.point = centroidPointRing;
33956   centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y);
33957 }
33958
33959 function centroidPointRing(x, y) {
33960   var dx = x - x0$3,
33961       dy = y - y0$3,
33962       z = sqrt$1(dx * dx + dy * dy);
33963
33964   X1$1 += z * (x0$3 + x) / 2;
33965   Y1$1 += z * (y0$3 + y) / 2;
33966   Z1$1 += z;
33967
33968   z = y0$3 * x - x0$3 * y;
33969   X2$1 += z * (x0$3 + x);
33970   Y2$1 += z * (y0$3 + y);
33971   Z2$1 += z * 3;
33972   centroidPoint$1(x0$3 = x, y0$3 = y);
33973 }
33974
33975 function PathContext(context) {
33976   this._context = context;
33977 }
33978
33979 PathContext.prototype = {
33980   _radius: 4.5,
33981   pointRadius: function(_) {
33982     return this._radius = _, this;
33983   },
33984   polygonStart: function() {
33985     this._line = 0;
33986   },
33987   polygonEnd: function() {
33988     this._line = NaN;
33989   },
33990   lineStart: function() {
33991     this._point = 0;
33992   },
33993   lineEnd: function() {
33994     if (this._line === 0) this._context.closePath();
33995     this._point = NaN;
33996   },
33997   point: function(x, y) {
33998     switch (this._point) {
33999       case 0: {
34000         this._context.moveTo(x, y);
34001         this._point = 1;
34002         break;
34003       }
34004       case 1: {
34005         this._context.lineTo(x, y);
34006         break;
34007       }
34008       default: {
34009         this._context.moveTo(x + this._radius, y);
34010         this._context.arc(x, y, this._radius, 0, tau$4);
34011         break;
34012       }
34013     }
34014   },
34015   result: noop$2
34016 };
34017
34018 function PathString() {
34019   this._string = [];
34020 }
34021
34022 PathString.prototype = {
34023   _circle: circle$2(4.5),
34024   pointRadius: function(_) {
34025     return this._circle = circle$2(_), this;
34026   },
34027   polygonStart: function() {
34028     this._line = 0;
34029   },
34030   polygonEnd: function() {
34031     this._line = NaN;
34032   },
34033   lineStart: function() {
34034     this._point = 0;
34035   },
34036   lineEnd: function() {
34037     if (this._line === 0) this._string.push("Z");
34038     this._point = NaN;
34039   },
34040   point: function(x, y) {
34041     switch (this._point) {
34042       case 0: {
34043         this._string.push("M", x, ",", y);
34044         this._point = 1;
34045         break;
34046       }
34047       case 1: {
34048         this._string.push("L", x, ",", y);
34049         break;
34050       }
34051       default: {
34052         this._string.push("M", x, ",", y, this._circle);
34053         break;
34054       }
34055     }
34056   },
34057   result: function() {
34058     if (this._string.length) {
34059       var result = this._string.join("");
34060       this._string = [];
34061       return result;
34062     }
34063   }
34064 };
34065
34066 function circle$2(radius) {
34067   return "m0," + radius
34068       + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
34069       + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
34070       + "z";
34071 }
34072
34073 var index$5 = function(projection, context) {
34074   var pointRadius = 4.5,
34075       projectionStream,
34076       contextStream;
34077
34078   function path(object) {
34079     if (object) {
34080       if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
34081       geoStream(object, projectionStream(contextStream));
34082     }
34083     return contextStream.result();
34084   }
34085
34086   path.area = function(object) {
34087     geoStream(object, projectionStream(areaStream$1));
34088     return areaStream$1.result();
34089   };
34090
34091   path.bounds = function(object) {
34092     geoStream(object, projectionStream(boundsStream$1));
34093     return boundsStream$1.result();
34094   };
34095
34096   path.centroid = function(object) {
34097     geoStream(object, projectionStream(centroidStream$1));
34098     return centroidStream$1.result();
34099   };
34100
34101   path.projection = function(_) {
34102     return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$7) : (projection = _).stream, path) : projection;
34103   };
34104
34105   path.context = function(_) {
34106     if (!arguments.length) return context;
34107     contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _);
34108     if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
34109     return path;
34110   };
34111
34112   path.pointRadius = function(_) {
34113     if (!arguments.length) return pointRadius;
34114     pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
34115     return path;
34116   };
34117
34118   return path.projection(projection).context(context);
34119 };
34120
34121 var sum$2 = adder();
34122
34123 var polygonContains = function(polygon, point) {
34124   var lambda = point[0],
34125       phi = point[1],
34126       normal = [sin$1(lambda), -cos$1(lambda), 0],
34127       angle = 0,
34128       winding = 0;
34129
34130   sum$2.reset();
34131
34132   for (var i = 0, n = polygon.length; i < n; ++i) {
34133     if (!(m = (ring = polygon[i]).length)) continue;
34134     var ring,
34135         m,
34136         point0 = ring[m - 1],
34137         lambda0 = point0[0],
34138         phi0 = point0[1] / 2 + quarterPi,
34139         sinPhi0 = sin$1(phi0),
34140         cosPhi0 = cos$1(phi0);
34141
34142     for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
34143       var point1 = ring[j],
34144           lambda1 = point1[0],
34145           phi1 = point1[1] / 2 + quarterPi,
34146           sinPhi1 = sin$1(phi1),
34147           cosPhi1 = cos$1(phi1),
34148           delta = lambda1 - lambda0,
34149           sign$$1 = delta >= 0 ? 1 : -1,
34150           absDelta = sign$$1 * delta,
34151           antimeridian = absDelta > pi$4,
34152           k = sinPhi0 * sinPhi1;
34153
34154       sum$2.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta)));
34155       angle += antimeridian ? delta + sign$$1 * tau$4 : delta;
34156
34157       // Are the longitudes either side of the point’s meridian (lambda),
34158       // and are the latitudes smaller than the parallel (phi)?
34159       if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
34160         var arc = cartesianCross(cartesian(point0), cartesian(point1));
34161         cartesianNormalizeInPlace(arc);
34162         var intersection = cartesianCross(normal, arc);
34163         cartesianNormalizeInPlace(intersection);
34164         var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin$1(intersection[2]);
34165         if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
34166           winding += antimeridian ^ delta >= 0 ? 1 : -1;
34167         }
34168       }
34169     }
34170   }
34171
34172   // First, determine whether the South pole is inside or outside:
34173   //
34174   // It is inside if:
34175   // * the polygon winds around it in a clockwise direction.
34176   // * the polygon does not (cumulatively) wind around it, but has a negative
34177   //   (counter-clockwise) area.
34178   //
34179   // Second, count the (signed) number of times a segment crosses a lambda
34180   // from the point to the South pole.  If it is zero, then the point is the
34181   // same side as the South pole.
34182
34183   return (angle < -epsilon$4 || angle < epsilon$4 && sum$2 < -epsilon$4) ^ (winding & 1);
34184 };
34185
34186 var clip = function(pointVisible, clipLine, interpolate, start) {
34187   return function(rotate, sink) {
34188     var line = clipLine(sink),
34189         rotatedStart = rotate.invert(start[0], start[1]),
34190         ringBuffer = clipBuffer(),
34191         ringSink = clipLine(ringBuffer),
34192         polygonStarted = false,
34193         polygon,
34194         segments,
34195         ring;
34196
34197     var clip = {
34198       point: point,
34199       lineStart: lineStart,
34200       lineEnd: lineEnd,
34201       polygonStart: function() {
34202         clip.point = pointRing;
34203         clip.lineStart = ringStart;
34204         clip.lineEnd = ringEnd;
34205         segments = [];
34206         polygon = [];
34207       },
34208       polygonEnd: function() {
34209         clip.point = point;
34210         clip.lineStart = lineStart;
34211         clip.lineEnd = lineEnd;
34212         segments = merge(segments);
34213         var startInside = polygonContains(polygon, rotatedStart);
34214         if (segments.length) {
34215           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34216           clipPolygon(segments, compareIntersection, startInside, interpolate, sink);
34217         } else if (startInside) {
34218           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34219           sink.lineStart();
34220           interpolate(null, null, 1, sink);
34221           sink.lineEnd();
34222         }
34223         if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
34224         segments = polygon = null;
34225       },
34226       sphere: function() {
34227         sink.polygonStart();
34228         sink.lineStart();
34229         interpolate(null, null, 1, sink);
34230         sink.lineEnd();
34231         sink.polygonEnd();
34232       }
34233     };
34234
34235     function point(lambda, phi) {
34236       var point = rotate(lambda, phi);
34237       if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
34238     }
34239
34240     function pointLine(lambda, phi) {
34241       var point = rotate(lambda, phi);
34242       line.point(point[0], point[1]);
34243     }
34244
34245     function lineStart() {
34246       clip.point = pointLine;
34247       line.lineStart();
34248     }
34249
34250     function lineEnd() {
34251       clip.point = point;
34252       line.lineEnd();
34253     }
34254
34255     function pointRing(lambda, phi) {
34256       ring.push([lambda, phi]);
34257       var point = rotate(lambda, phi);
34258       ringSink.point(point[0], point[1]);
34259     }
34260
34261     function ringStart() {
34262       ringSink.lineStart();
34263       ring = [];
34264     }
34265
34266     function ringEnd() {
34267       pointRing(ring[0][0], ring[0][1]);
34268       ringSink.lineEnd();
34269
34270       var clean = ringSink.clean(),
34271           ringSegments = ringBuffer.result(),
34272           i, n = ringSegments.length, m,
34273           segment,
34274           point;
34275
34276       ring.pop();
34277       polygon.push(ring);
34278       ring = null;
34279
34280       if (!n) return;
34281
34282       // No intersections.
34283       if (clean & 1) {
34284         segment = ringSegments[0];
34285         if ((m = segment.length - 1) > 0) {
34286           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34287           sink.lineStart();
34288           for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
34289           sink.lineEnd();
34290         }
34291         return;
34292       }
34293
34294       // Rejoin connected segments.
34295       // TODO reuse ringBuffer.rejoin()?
34296       if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
34297
34298       segments.push(ringSegments.filter(validSegment));
34299     }
34300
34301     return clip;
34302   };
34303 };
34304
34305 function validSegment(segment) {
34306   return segment.length > 1;
34307 }
34308
34309 // Intersections are sorted along the clip edge. For both antimeridian cutting
34310 // and circle clipping, the same comparison is used.
34311 function compareIntersection(a, b) {
34312   return ((a = a.x)[0] < 0 ? a[1] - halfPi$3 - epsilon$4 : halfPi$3 - a[1])
34313        - ((b = b.x)[0] < 0 ? b[1] - halfPi$3 - epsilon$4 : halfPi$3 - b[1]);
34314 }
34315
34316 var clipAntimeridian = clip(
34317   function() { return true; },
34318   clipAntimeridianLine,
34319   clipAntimeridianInterpolate,
34320   [-pi$4, -halfPi$3]
34321 );
34322
34323 // Takes a line and cuts into visible segments. Return values: 0 - there were
34324 // intersections or the line was empty; 1 - no intersections; 2 - there were
34325 // intersections, and the first and last segments should be rejoined.
34326 function clipAntimeridianLine(stream) {
34327   var lambda0 = NaN,
34328       phi0 = NaN,
34329       sign0 = NaN,
34330       clean; // no intersections
34331
34332   return {
34333     lineStart: function() {
34334       stream.lineStart();
34335       clean = 1;
34336     },
34337     point: function(lambda1, phi1) {
34338       var sign1 = lambda1 > 0 ? pi$4 : -pi$4,
34339           delta = abs(lambda1 - lambda0);
34340       if (abs(delta - pi$4) < epsilon$4) { // line crosses a pole
34341         stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$3 : -halfPi$3);
34342         stream.point(sign0, phi0);
34343         stream.lineEnd();
34344         stream.lineStart();
34345         stream.point(sign1, phi0);
34346         stream.point(lambda1, phi0);
34347         clean = 0;
34348       } else if (sign0 !== sign1 && delta >= pi$4) { // line crosses antimeridian
34349         if (abs(lambda0 - sign0) < epsilon$4) lambda0 -= sign0 * epsilon$4; // handle degeneracies
34350         if (abs(lambda1 - sign1) < epsilon$4) lambda1 -= sign1 * epsilon$4;
34351         phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
34352         stream.point(sign0, phi0);
34353         stream.lineEnd();
34354         stream.lineStart();
34355         stream.point(sign1, phi0);
34356         clean = 0;
34357       }
34358       stream.point(lambda0 = lambda1, phi0 = phi1);
34359       sign0 = sign1;
34360     },
34361     lineEnd: function() {
34362       stream.lineEnd();
34363       lambda0 = phi0 = NaN;
34364     },
34365     clean: function() {
34366       return 2 - clean; // if intersections, rejoin first and last segments
34367     }
34368   };
34369 }
34370
34371 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
34372   var cosPhi0,
34373       cosPhi1,
34374       sinLambda0Lambda1 = sin$1(lambda0 - lambda1);
34375   return abs(sinLambda0Lambda1) > epsilon$4
34376       ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1)
34377           - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0))
34378           / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
34379       : (phi0 + phi1) / 2;
34380 }
34381
34382 function clipAntimeridianInterpolate(from, to, direction, stream) {
34383   var phi;
34384   if (from == null) {
34385     phi = direction * halfPi$3;
34386     stream.point(-pi$4, phi);
34387     stream.point(0, phi);
34388     stream.point(pi$4, phi);
34389     stream.point(pi$4, 0);
34390     stream.point(pi$4, -phi);
34391     stream.point(0, -phi);
34392     stream.point(-pi$4, -phi);
34393     stream.point(-pi$4, 0);
34394     stream.point(-pi$4, phi);
34395   } else if (abs(from[0] - to[0]) > epsilon$4) {
34396     var lambda = from[0] < to[0] ? pi$4 : -pi$4;
34397     phi = direction * lambda / 2;
34398     stream.point(-lambda, phi);
34399     stream.point(0, phi);
34400     stream.point(lambda, phi);
34401   } else {
34402     stream.point(to[0], to[1]);
34403   }
34404 }
34405
34406 var clipCircle = function(radius, delta) {
34407   var cr = cos$1(radius),
34408       smallRadius = cr > 0,
34409       notHemisphere = abs(cr) > epsilon$4; // TODO optimise for this common case
34410
34411   function interpolate(from, to, direction, stream) {
34412     circleStream(stream, radius, delta, direction, from, to);
34413   }
34414
34415   function visible(lambda, phi) {
34416     return cos$1(lambda) * cos$1(phi) > cr;
34417   }
34418
34419   // Takes a line and cuts into visible segments. Return values used for polygon
34420   // clipping: 0 - there were intersections or the line was empty; 1 - no
34421   // intersections 2 - there were intersections, and the first and last segments
34422   // should be rejoined.
34423   function clipLine(stream) {
34424     var point0, // previous point
34425         c0, // code for previous point
34426         v0, // visibility of previous point
34427         v00, // visibility of first point
34428         clean; // no intersections
34429     return {
34430       lineStart: function() {
34431         v00 = v0 = false;
34432         clean = 1;
34433       },
34434       point: function(lambda, phi) {
34435         var point1 = [lambda, phi],
34436             point2,
34437             v = visible(lambda, phi),
34438             c = smallRadius
34439               ? v ? 0 : code(lambda, phi)
34440               : v ? code(lambda + (lambda < 0 ? pi$4 : -pi$4), phi) : 0;
34441         if (!point0 && (v00 = v0 = v)) stream.lineStart();
34442         // Handle degeneracies.
34443         // TODO ignore if not clipping polygons.
34444         if (v !== v0) {
34445           point2 = intersect(point0, point1);
34446           if (pointEqual(point0, point2) || pointEqual(point1, point2)) {
34447             point1[0] += epsilon$4;
34448             point1[1] += epsilon$4;
34449             v = visible(point1[0], point1[1]);
34450           }
34451         }
34452         if (v !== v0) {
34453           clean = 0;
34454           if (v) {
34455             // outside going in
34456             stream.lineStart();
34457             point2 = intersect(point1, point0);
34458             stream.point(point2[0], point2[1]);
34459           } else {
34460             // inside going out
34461             point2 = intersect(point0, point1);
34462             stream.point(point2[0], point2[1]);
34463             stream.lineEnd();
34464           }
34465           point0 = point2;
34466         } else if (notHemisphere && point0 && smallRadius ^ v) {
34467           var t;
34468           // If the codes for two points are different, or are both zero,
34469           // and there this segment intersects with the small circle.
34470           if (!(c & c0) && (t = intersect(point1, point0, true))) {
34471             clean = 0;
34472             if (smallRadius) {
34473               stream.lineStart();
34474               stream.point(t[0][0], t[0][1]);
34475               stream.point(t[1][0], t[1][1]);
34476               stream.lineEnd();
34477             } else {
34478               stream.point(t[1][0], t[1][1]);
34479               stream.lineEnd();
34480               stream.lineStart();
34481               stream.point(t[0][0], t[0][1]);
34482             }
34483           }
34484         }
34485         if (v && (!point0 || !pointEqual(point0, point1))) {
34486           stream.point(point1[0], point1[1]);
34487         }
34488         point0 = point1, v0 = v, c0 = c;
34489       },
34490       lineEnd: function() {
34491         if (v0) stream.lineEnd();
34492         point0 = null;
34493       },
34494       // Rejoin first and last segments if there were intersections and the first
34495       // and last points were visible.
34496       clean: function() {
34497         return clean | ((v00 && v0) << 1);
34498       }
34499     };
34500   }
34501
34502   // Intersects the great circle between a and b with the clip circle.
34503   function intersect(a, b, two) {
34504     var pa = cartesian(a),
34505         pb = cartesian(b);
34506
34507     // We have two planes, n1.p = d1 and n2.p = d2.
34508     // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
34509     var n1 = [1, 0, 0], // normal
34510         n2 = cartesianCross(pa, pb),
34511         n2n2 = cartesianDot(n2, n2),
34512         n1n2 = n2[0], // cartesianDot(n1, n2),
34513         determinant = n2n2 - n1n2 * n1n2;
34514
34515     // Two polar points.
34516     if (!determinant) return !two && a;
34517
34518     var c1 =  cr * n2n2 / determinant,
34519         c2 = -cr * n1n2 / determinant,
34520         n1xn2 = cartesianCross(n1, n2),
34521         A = cartesianScale(n1, c1),
34522         B = cartesianScale(n2, c2);
34523     cartesianAddInPlace(A, B);
34524
34525     // Solve |p(t)|^2 = 1.
34526     var u = n1xn2,
34527         w = cartesianDot(A, u),
34528         uu = cartesianDot(u, u),
34529         t2 = w * w - uu * (cartesianDot(A, A) - 1);
34530
34531     if (t2 < 0) return;
34532
34533     var t = sqrt$1(t2),
34534         q = cartesianScale(u, (-w - t) / uu);
34535     cartesianAddInPlace(q, A);
34536     q = spherical(q);
34537
34538     if (!two) return q;
34539
34540     // Two intersection points.
34541     var lambda0 = a[0],
34542         lambda1 = b[0],
34543         phi0 = a[1],
34544         phi1 = b[1],
34545         z;
34546
34547     if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
34548
34549     var delta = lambda1 - lambda0,
34550         polar = abs(delta - pi$4) < epsilon$4,
34551         meridian = polar || delta < epsilon$4;
34552
34553     if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
34554
34555     // Check that the first point is between a and b.
34556     if (meridian
34557         ? polar
34558           ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$4 ? phi0 : phi1)
34559           : phi0 <= q[1] && q[1] <= phi1
34560         : delta > pi$4 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
34561       var q1 = cartesianScale(u, (-w + t) / uu);
34562       cartesianAddInPlace(q1, A);
34563       return [q, spherical(q1)];
34564     }
34565   }
34566
34567   // Generates a 4-bit vector representing the location of a point relative to
34568   // the small circle's bounding box.
34569   function code(lambda, phi) {
34570     var r = smallRadius ? radius : pi$4 - radius,
34571         code = 0;
34572     if (lambda < -r) code |= 1; // left
34573     else if (lambda > r) code |= 2; // right
34574     if (phi < -r) code |= 4; // below
34575     else if (phi > r) code |= 8; // above
34576     return code;
34577   }
34578
34579   return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$4, radius - pi$4]);
34580 };
34581
34582 var transform$1 = function(methods) {
34583   return {
34584     stream: transformer(methods)
34585   };
34586 };
34587
34588 function transformer(methods) {
34589   return function(stream) {
34590     var s = new TransformStream;
34591     for (var key in methods) s[key] = methods[key];
34592     s.stream = stream;
34593     return s;
34594   };
34595 }
34596
34597 function TransformStream() {}
34598
34599 TransformStream.prototype = {
34600   constructor: TransformStream,
34601   point: function(x, y) { this.stream.point(x, y); },
34602   sphere: function() { this.stream.sphere(); },
34603   lineStart: function() { this.stream.lineStart(); },
34604   lineEnd: function() { this.stream.lineEnd(); },
34605   polygonStart: function() { this.stream.polygonStart(); },
34606   polygonEnd: function() { this.stream.polygonEnd(); }
34607 };
34608
34609 function fitExtent(projection, extent, object) {
34610   var w = extent[1][0] - extent[0][0],
34611       h = extent[1][1] - extent[0][1],
34612       clip = projection.clipExtent && projection.clipExtent();
34613
34614   projection
34615       .scale(150)
34616       .translate([0, 0]);
34617
34618   if (clip != null) projection.clipExtent(null);
34619
34620   geoStream(object, projection.stream(boundsStream$1));
34621
34622   var b = boundsStream$1.result(),
34623       k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
34624       x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
34625       y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
34626
34627   if (clip != null) projection.clipExtent(clip);
34628
34629   return projection
34630       .scale(k * 150)
34631       .translate([x, y]);
34632 }
34633
34634 function fitSize(projection, size, object) {
34635   return fitExtent(projection, [[0, 0], size], object);
34636 }
34637
34638 var maxDepth = 16;
34639 var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance)
34640
34641 var resample = function(project, delta2) {
34642   return +delta2 ? resample$1(project, delta2) : resampleNone(project);
34643 };
34644
34645 function resampleNone(project) {
34646   return transformer({
34647     point: function(x, y) {
34648       x = project(x, y);
34649       this.stream.point(x[0], x[1]);
34650     }
34651   });
34652 }
34653
34654 function resample$1(project, delta2) {
34655
34656   function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
34657     var dx = x1 - x0,
34658         dy = y1 - y0,
34659         d2 = dx * dx + dy * dy;
34660     if (d2 > 4 * delta2 && depth--) {
34661       var a = a0 + a1,
34662           b = b0 + b1,
34663           c = c0 + c1,
34664           m = sqrt$1(a * a + b * b + c * c),
34665           phi2 = asin$1(c /= m),
34666           lambda2 = abs(abs(c) - 1) < epsilon$4 || abs(lambda0 - lambda1) < epsilon$4 ? (lambda0 + lambda1) / 2 : atan2(b, a),
34667           p = project(lambda2, phi2),
34668           x2 = p[0],
34669           y2 = p[1],
34670           dx2 = x2 - x0,
34671           dy2 = y2 - y0,
34672           dz = dy * dx2 - dx * dy2;
34673       if (dz * dz / d2 > delta2 // perpendicular projected distance
34674           || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
34675           || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
34676         resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
34677         stream.point(x2, y2);
34678         resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
34679       }
34680     }
34681   }
34682   return function(stream) {
34683     var lambda00, x00, y00, a00, b00, c00, // first point
34684         lambda0, x0, y0, a0, b0, c0; // previous point
34685
34686     var resampleStream = {
34687       point: point,
34688       lineStart: lineStart,
34689       lineEnd: lineEnd,
34690       polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
34691       polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
34692     };
34693
34694     function point(x, y) {
34695       x = project(x, y);
34696       stream.point(x[0], x[1]);
34697     }
34698
34699     function lineStart() {
34700       x0 = NaN;
34701       resampleStream.point = linePoint;
34702       stream.lineStart();
34703     }
34704
34705     function linePoint(lambda, phi) {
34706       var c = cartesian([lambda, phi]), p = project(lambda, phi);
34707       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);
34708       stream.point(x0, y0);
34709     }
34710
34711     function lineEnd() {
34712       resampleStream.point = point;
34713       stream.lineEnd();
34714     }
34715
34716     function ringStart() {
34717       lineStart();
34718       resampleStream.point = ringPoint;
34719       resampleStream.lineEnd = ringEnd;
34720     }
34721
34722     function ringPoint(lambda, phi) {
34723       linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
34724       resampleStream.point = linePoint;
34725     }
34726
34727     function ringEnd() {
34728       resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
34729       resampleStream.lineEnd = lineEnd;
34730       lineEnd();
34731     }
34732
34733     return resampleStream;
34734   };
34735 }
34736
34737 var transformRadians = transformer({
34738   point: function(x, y) {
34739     this.stream.point(x * radians, y * radians);
34740   }
34741 });
34742
34743 function projection(project) {
34744   return projectionMutator(function() { return project; })();
34745 }
34746
34747 function projectionMutator(projectAt) {
34748   var project,
34749       k = 150, // scale
34750       x = 480, y = 250, // translate
34751       dx, dy, lambda = 0, phi = 0, // center
34752       deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
34753       theta = null, preclip = clipAntimeridian, // clip angle
34754       x0 = null, y0, x1, y1, postclip = identity$7, // clip extent
34755       delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
34756       cache,
34757       cacheStream;
34758
34759   function projection(point) {
34760     point = projectRotate(point[0] * radians, point[1] * radians);
34761     return [point[0] * k + dx, dy - point[1] * k];
34762   }
34763
34764   function invert(point) {
34765     point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
34766     return point && [point[0] * degrees$1, point[1] * degrees$1];
34767   }
34768
34769   function projectTransform(x, y) {
34770     return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
34771   }
34772
34773   projection.stream = function(stream) {
34774     return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
34775   };
34776
34777   projection.clipAngle = function(_) {
34778     return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
34779   };
34780
34781   projection.clipExtent = function(_) {
34782     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]];
34783   };
34784
34785   projection.scale = function(_) {
34786     return arguments.length ? (k = +_, recenter()) : k;
34787   };
34788
34789   projection.translate = function(_) {
34790     return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
34791   };
34792
34793   projection.center = function(_) {
34794     return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
34795   };
34796
34797   projection.rotate = function(_) {
34798     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];
34799   };
34800
34801   projection.precision = function(_) {
34802     return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt$1(delta2);
34803   };
34804
34805   projection.fitExtent = function(extent, object) {
34806     return fitExtent(projection, extent, object);
34807   };
34808
34809   projection.fitSize = function(size, object) {
34810     return fitSize(projection, size, object);
34811   };
34812
34813   function recenter() {
34814     projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
34815     var center = project(lambda, phi);
34816     dx = x - center[0] * k;
34817     dy = y + center[1] * k;
34818     return reset();
34819   }
34820
34821   function reset() {
34822     cache = cacheStream = null;
34823     return projection;
34824   }
34825
34826   return function() {
34827     project = projectAt.apply(this, arguments);
34828     projection.invert = project.invert && invert;
34829     return recenter();
34830   };
34831 }
34832
34833 function conicProjection(projectAt) {
34834   var phi0 = 0,
34835       phi1 = pi$4 / 3,
34836       m = projectionMutator(projectAt),
34837       p = m(phi0, phi1);
34838
34839   p.parallels = function(_) {
34840     return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1];
34841   };
34842
34843   return p;
34844 }
34845
34846 function cylindricalEqualAreaRaw(phi0) {
34847   var cosPhi0 = cos$1(phi0);
34848
34849   function forward(lambda, phi) {
34850     return [lambda * cosPhi0, sin$1(phi) / cosPhi0];
34851   }
34852
34853   forward.invert = function(x, y) {
34854     return [x / cosPhi0, asin$1(y * cosPhi0)];
34855   };
34856
34857   return forward;
34858 }
34859
34860 function conicEqualAreaRaw(y0, y1) {
34861   var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2;
34862
34863   // Are the parallels symmetrical around the Equator?
34864   if (abs(n) < epsilon$4) return cylindricalEqualAreaRaw(y0);
34865
34866   var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt$1(c) / n;
34867
34868   function project(x, y) {
34869     var r = sqrt$1(c - 2 * n * sin$1(y)) / n;
34870     return [r * sin$1(x *= n), r0 - r * cos$1(x)];
34871   }
34872
34873   project.invert = function(x, y) {
34874     var r0y = r0 - y;
34875     return [atan2(x, abs(r0y)) / n * sign$1(r0y), asin$1((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
34876   };
34877
34878   return project;
34879 }
34880
34881 var conicEqualArea = function() {
34882   return conicProjection(conicEqualAreaRaw)
34883       .scale(155.424)
34884       .center([0, 33.6442]);
34885 };
34886
34887 var albers = function() {
34888   return conicEqualArea()
34889       .parallels([29.5, 45.5])
34890       .scale(1070)
34891       .translate([480, 250])
34892       .rotate([96, 0])
34893       .center([-0.6, 38.7]);
34894 };
34895
34896 // The projections must have mutually exclusive clip regions on the sphere,
34897 // as this will avoid emitting interleaving lines and polygons.
34898 function multiplex(streams) {
34899   var n = streams.length;
34900   return {
34901     point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
34902     sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
34903     lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
34904     lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
34905     polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
34906     polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
34907   };
34908 }
34909
34910 // A composite projection for the United States, configured by default for
34911 // 960×500. The projection also works quite well at 960×600 if you change the
34912 // scale to 1285 and adjust the translate accordingly. The set of standard
34913 // parallels for each region comes from USGS, which is published here:
34914 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
34915 var albersUsa = function() {
34916   var cache,
34917       cacheStream,
34918       lower48 = albers(), lower48Point,
34919       alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
34920       hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
34921       point, pointStream = {point: function(x, y) { point = [x, y]; }};
34922
34923   function albersUsa(coordinates) {
34924     var x = coordinates[0], y = coordinates[1];
34925     return point = null,
34926         (lower48Point.point(x, y), point)
34927         || (alaskaPoint.point(x, y), point)
34928         || (hawaiiPoint.point(x, y), point);
34929   }
34930
34931   albersUsa.invert = function(coordinates) {
34932     var k = lower48.scale(),
34933         t = lower48.translate(),
34934         x = (coordinates[0] - t[0]) / k,
34935         y = (coordinates[1] - t[1]) / k;
34936     return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
34937         : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
34938         : lower48).invert(coordinates);
34939   };
34940
34941   albersUsa.stream = function(stream) {
34942     return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
34943   };
34944
34945   albersUsa.precision = function(_) {
34946     if (!arguments.length) return lower48.precision();
34947     lower48.precision(_), alaska.precision(_), hawaii.precision(_);
34948     return reset();
34949   };
34950
34951   albersUsa.scale = function(_) {
34952     if (!arguments.length) return lower48.scale();
34953     lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
34954     return albersUsa.translate(lower48.translate());
34955   };
34956
34957   albersUsa.translate = function(_) {
34958     if (!arguments.length) return lower48.translate();
34959     var k = lower48.scale(), x = +_[0], y = +_[1];
34960
34961     lower48Point = lower48
34962         .translate(_)
34963         .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
34964         .stream(pointStream);
34965
34966     alaskaPoint = alaska
34967         .translate([x - 0.307 * k, y + 0.201 * k])
34968         .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]])
34969         .stream(pointStream);
34970
34971     hawaiiPoint = hawaii
34972         .translate([x - 0.205 * k, y + 0.212 * k])
34973         .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]])
34974         .stream(pointStream);
34975
34976     return reset();
34977   };
34978
34979   albersUsa.fitExtent = function(extent, object) {
34980     return fitExtent(albersUsa, extent, object);
34981   };
34982
34983   albersUsa.fitSize = function(size, object) {
34984     return fitSize(albersUsa, size, object);
34985   };
34986
34987   function reset() {
34988     cache = cacheStream = null;
34989     return albersUsa;
34990   }
34991
34992   return albersUsa.scale(1070);
34993 };
34994
34995 function azimuthalRaw(scale) {
34996   return function(x, y) {
34997     var cx = cos$1(x),
34998         cy = cos$1(y),
34999         k = scale(cx * cy);
35000     return [
35001       k * cy * sin$1(x),
35002       k * sin$1(y)
35003     ];
35004   }
35005 }
35006
35007 function azimuthalInvert(angle) {
35008   return function(x, y) {
35009     var z = sqrt$1(x * x + y * y),
35010         c = angle(z),
35011         sc = sin$1(c),
35012         cc = cos$1(c);
35013     return [
35014       atan2(x * sc, z * cc),
35015       asin$1(z && y * sc / z)
35016     ];
35017   }
35018 }
35019
35020 var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
35021   return sqrt$1(2 / (1 + cxcy));
35022 });
35023
35024 azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
35025   return 2 * asin$1(z / 2);
35026 });
35027
35028 var azimuthalEqualArea = function() {
35029   return projection(azimuthalEqualAreaRaw)
35030       .scale(124.75)
35031       .clipAngle(180 - 1e-3);
35032 };
35033
35034 var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
35035   return (c = acos(c)) && c / sin$1(c);
35036 });
35037
35038 azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
35039   return z;
35040 });
35041
35042 var azimuthalEquidistant = function() {
35043   return projection(azimuthalEquidistantRaw)
35044       .scale(79.4188)
35045       .clipAngle(180 - 1e-3);
35046 };
35047
35048 function mercatorRaw(lambda, phi) {
35049   return [lambda, log$1(tan((halfPi$3 + phi) / 2))];
35050 }
35051
35052 mercatorRaw.invert = function(x, y) {
35053   return [x, 2 * atan(exp(y)) - halfPi$3];
35054 };
35055
35056 var mercator = function() {
35057   return mercatorProjection(mercatorRaw)
35058       .scale(961 / tau$4);
35059 };
35060
35061 function mercatorProjection(project) {
35062   var m = projection(project),
35063       scale = m.scale,
35064       translate = m.translate,
35065       clipExtent = m.clipExtent,
35066       clipAuto;
35067
35068   m.scale = function(_) {
35069     return arguments.length ? (scale(_), clipAuto && m.clipExtent(null), m) : scale();
35070   };
35071
35072   m.translate = function(_) {
35073     return arguments.length ? (translate(_), clipAuto && m.clipExtent(null), m) : translate();
35074   };
35075
35076   m.clipExtent = function(_) {
35077     if (!arguments.length) return clipAuto ? null : clipExtent();
35078     if (clipAuto = _ == null) {
35079       var k = pi$4 * scale(),
35080           t = translate();
35081       _ = [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]];
35082     }
35083     clipExtent(_);
35084     return m;
35085   };
35086
35087   return m.clipExtent(null);
35088 }
35089
35090 function tany(y) {
35091   return tan((halfPi$3 + y) / 2);
35092 }
35093
35094 function conicConformalRaw(y0, y1) {
35095   var cy0 = cos$1(y0),
35096       n = y0 === y1 ? sin$1(y0) : log$1(cy0 / cos$1(y1)) / log$1(tany(y1) / tany(y0)),
35097       f = cy0 * pow$1(tany(y0), n) / n;
35098
35099   if (!n) return mercatorRaw;
35100
35101   function project(x, y) {
35102     if (f > 0) { if (y < -halfPi$3 + epsilon$4) y = -halfPi$3 + epsilon$4; }
35103     else { if (y > halfPi$3 - epsilon$4) y = halfPi$3 - epsilon$4; }
35104     var r = f / pow$1(tany(y), n);
35105     return [r * sin$1(n * x), f - r * cos$1(n * x)];
35106   }
35107
35108   project.invert = function(x, y) {
35109     var fy = f - y, r = sign$1(n) * sqrt$1(x * x + fy * fy);
35110     return [atan2(x, abs(fy)) / n * sign$1(fy), 2 * atan(pow$1(f / r, 1 / n)) - halfPi$3];
35111   };
35112
35113   return project;
35114 }
35115
35116 var conicConformal = function() {
35117   return conicProjection(conicConformalRaw)
35118       .scale(109.5)
35119       .parallels([30, 30]);
35120 };
35121
35122 function equirectangularRaw(lambda, phi) {
35123   return [lambda, phi];
35124 }
35125
35126 equirectangularRaw.invert = equirectangularRaw;
35127
35128 var equirectangular = function() {
35129   return projection(equirectangularRaw)
35130       .scale(152.63);
35131 };
35132
35133 function conicEquidistantRaw(y0, y1) {
35134   var cy0 = cos$1(y0),
35135       n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0),
35136       g = cy0 / n + y0;
35137
35138   if (abs(n) < epsilon$4) return equirectangularRaw;
35139
35140   function project(x, y) {
35141     var gy = g - y, nx = n * x;
35142     return [gy * sin$1(nx), g - gy * cos$1(nx)];
35143   }
35144
35145   project.invert = function(x, y) {
35146     var gy = g - y;
35147     return [atan2(x, abs(gy)) / n * sign$1(gy), g - sign$1(n) * sqrt$1(x * x + gy * gy)];
35148   };
35149
35150   return project;
35151 }
35152
35153 var conicEquidistant = function() {
35154   return conicProjection(conicEquidistantRaw)
35155       .scale(131.154)
35156       .center([0, 13.9389]);
35157 };
35158
35159 function gnomonicRaw(x, y) {
35160   var cy = cos$1(y), k = cos$1(x) * cy;
35161   return [cy * sin$1(x) / k, sin$1(y) / k];
35162 }
35163
35164 gnomonicRaw.invert = azimuthalInvert(atan);
35165
35166 var gnomonic = function() {
35167   return projection(gnomonicRaw)
35168       .scale(144.049)
35169       .clipAngle(60);
35170 };
35171
35172 function scaleTranslate(kx, ky, tx, ty) {
35173   return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity$7 : transformer({
35174     point: function(x, y) {
35175       this.stream.point(x * kx + tx, y * ky + ty);
35176     }
35177   });
35178 }
35179
35180 var identity$8 = function() {
35181   var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform = identity$7, // scale, translate and reflect
35182       x0 = null, y0, x1, y1, clip = identity$7, // clip extent
35183       cache,
35184       cacheStream,
35185       projection;
35186
35187   function reset() {
35188     cache = cacheStream = null;
35189     return projection;
35190   }
35191
35192   return projection = {
35193     stream: function(stream) {
35194       return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream));
35195     },
35196     clipExtent: function(_) {
35197       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]];
35198     },
35199     scale: function(_) {
35200       return arguments.length ? (transform = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k;
35201     },
35202     translate: function(_) {
35203       return arguments.length ? (transform = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty];
35204     },
35205     reflectX: function(_) {
35206       return arguments.length ? (transform = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0;
35207     },
35208     reflectY: function(_) {
35209       return arguments.length ? (transform = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0;
35210     },
35211     fitExtent: function(extent, object) {
35212       return fitExtent(projection, extent, object);
35213     },
35214     fitSize: function(size, object) {
35215       return fitSize(projection, size, object);
35216     }
35217   };
35218 };
35219
35220 function orthographicRaw(x, y) {
35221   return [cos$1(y) * sin$1(x), sin$1(y)];
35222 }
35223
35224 orthographicRaw.invert = azimuthalInvert(asin$1);
35225
35226 var orthographic = function() {
35227   return projection(orthographicRaw)
35228       .scale(249.5)
35229       .clipAngle(90 + epsilon$4);
35230 };
35231
35232 function stereographicRaw(x, y) {
35233   var cy = cos$1(y), k = 1 + cos$1(x) * cy;
35234   return [cy * sin$1(x) / k, sin$1(y) / k];
35235 }
35236
35237 stereographicRaw.invert = azimuthalInvert(function(z) {
35238   return 2 * atan(z);
35239 });
35240
35241 var stereographic = function() {
35242   return projection(stereographicRaw)
35243       .scale(250)
35244       .clipAngle(142);
35245 };
35246
35247 function transverseMercatorRaw(lambda, phi) {
35248   return [log$1(tan((halfPi$3 + phi) / 2)), -lambda];
35249 }
35250
35251 transverseMercatorRaw.invert = function(x, y) {
35252   return [-y, 2 * atan(exp(x)) - halfPi$3];
35253 };
35254
35255 var transverseMercator = function() {
35256   var m = mercatorProjection(transverseMercatorRaw),
35257       center = m.center,
35258       rotate = m.rotate;
35259
35260   m.center = function(_) {
35261     return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
35262   };
35263
35264   m.rotate = function(_) {
35265     return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
35266   };
35267
35268   return rotate([0, 0, 90])
35269       .scale(159.155);
35270 };
35271
35272
35273
35274 var index$1 = Object.freeze({
35275         version: version,
35276         bisect: bisectRight,
35277         bisectRight: bisectRight,
35278         bisectLeft: bisectLeft,
35279         ascending: ascending,
35280         bisector: bisector,
35281         descending: descending,
35282         deviation: deviation,
35283         extent: extent,
35284         histogram: histogram,
35285         thresholdFreedmanDiaconis: freedmanDiaconis,
35286         thresholdScott: scott,
35287         thresholdSturges: sturges,
35288         max: max,
35289         mean: mean,
35290         median: median,
35291         merge: merge,
35292         min: min,
35293         pairs: pairs,
35294         permute: permute,
35295         quantile: threshold,
35296         range: range,
35297         scan: scan,
35298         shuffle: shuffle,
35299         sum: sum,
35300         ticks: ticks,
35301         tickStep: tickStep,
35302         transpose: transpose,
35303         variance: variance,
35304         zip: zip,
35305         entries: entries,
35306         keys: keys,
35307         values: values,
35308         map: map$1,
35309         set: set,
35310         nest: nest,
35311         randomUniform: uniform,
35312         randomNormal: normal,
35313         randomLogNormal: logNormal,
35314         randomBates: bates,
35315         randomIrwinHall: irwinHall,
35316         randomExponential: exponential,
35317         easeLinear: linear,
35318         easeQuad: quadInOut,
35319         easeQuadIn: quadIn,
35320         easeQuadOut: quadOut,
35321         easeQuadInOut: quadInOut,
35322         easeCubic: cubicInOut,
35323         easeCubicIn: cubicIn,
35324         easeCubicOut: cubicOut,
35325         easeCubicInOut: cubicInOut,
35326         easePoly: polyInOut,
35327         easePolyIn: polyIn,
35328         easePolyOut: polyOut,
35329         easePolyInOut: polyInOut,
35330         easeSin: sinInOut,
35331         easeSinIn: sinIn,
35332         easeSinOut: sinOut,
35333         easeSinInOut: sinInOut,
35334         easeExp: expInOut,
35335         easeExpIn: expIn,
35336         easeExpOut: expOut,
35337         easeExpInOut: expInOut,
35338         easeCircle: circleInOut,
35339         easeCircleIn: circleIn,
35340         easeCircleOut: circleOut,
35341         easeCircleInOut: circleInOut,
35342         easeBounce: bounceOut,
35343         easeBounceIn: bounceIn,
35344         easeBounceOut: bounceOut,
35345         easeBounceInOut: bounceInOut,
35346         easeBack: backInOut,
35347         easeBackIn: backIn,
35348         easeBackOut: backOut,
35349         easeBackInOut: backInOut,
35350         easeElastic: elasticOut,
35351         easeElasticIn: elasticIn,
35352         easeElasticOut: elasticOut,
35353         easeElasticInOut: elasticInOut,
35354         polygonArea: d3polygonArea,
35355         polygonCentroid: d3polygonCentroid,
35356         polygonHull: d3polygonHull,
35357         polygonContains: contains,
35358         polygonLength: length$1,
35359         path: path,
35360         quadtree: quadtree,
35361         queue: queue,
35362         arc: arc,
35363         area: area,
35364         line: line,
35365         pie: pie,
35366         radialArea: radialArea,
35367         radialLine: radialLine$1,
35368         symbol: symbol,
35369         symbols: symbols,
35370         symbolCircle: circle,
35371         symbolCross: cross$1,
35372         symbolDiamond: diamond,
35373         symbolSquare: square,
35374         symbolStar: star,
35375         symbolTriangle: triangle,
35376         symbolWye: wye,
35377         curveBasisClosed: basisClosed,
35378         curveBasisOpen: basisOpen,
35379         curveBasis: basis,
35380         curveBundle: bundle,
35381         curveCardinalClosed: cardinalClosed,
35382         curveCardinalOpen: cardinalOpen,
35383         curveCardinal: cardinal,
35384         curveCatmullRomClosed: catmullRomClosed,
35385         curveCatmullRomOpen: catmullRomOpen,
35386         curveCatmullRom: catmullRom,
35387         curveLinearClosed: linearClosed,
35388         curveLinear: curveLinear,
35389         curveMonotoneX: monotoneX,
35390         curveMonotoneY: monotoneY,
35391         curveNatural: natural,
35392         curveStep: step,
35393         curveStepAfter: stepAfter,
35394         curveStepBefore: stepBefore,
35395         stack: stack,
35396         stackOffsetExpand: expand,
35397         stackOffsetNone: none,
35398         stackOffsetSilhouette: silhouette,
35399         stackOffsetWiggle: wiggle,
35400         stackOrderAscending: ascending$1,
35401         stackOrderDescending: descending$2,
35402         stackOrderInsideOut: insideOut,
35403         stackOrderNone: none$1,
35404         stackOrderReverse: reverse,
35405         color: color,
35406         rgb: rgb,
35407         hsl: hsl,
35408         lab: lab,
35409         hcl: hcl,
35410         cubehelix: cubehelix,
35411         interpolate: interpolate,
35412         interpolateArray: array$1,
35413         interpolateDate: date,
35414         interpolateNumber: interpolateNumber,
35415         interpolateObject: object,
35416         interpolateRound: interpolateRound,
35417         interpolateString: interpolateString,
35418         interpolateTransformCss: interpolateTransformCss,
35419         interpolateTransformSvg: interpolateTransformSvg,
35420         interpolateZoom: interpolateZoom,
35421         interpolateRgb: interpolateRgb,
35422         interpolateRgbBasis: rgbBasis,
35423         interpolateRgbBasisClosed: rgbBasisClosed,
35424         interpolateHsl: hsl$2,
35425         interpolateHslLong: hslLong,
35426         interpolateLab: lab$1,
35427         interpolateHcl: hcl$2,
35428         interpolateHclLong: hclLong,
35429         interpolateCubehelix: cubehelix$2,
35430         interpolateCubehelixLong: cubehelixLong,
35431         interpolateBasis: basis$2,
35432         interpolateBasisClosed: basisClosed$1,
35433         quantize: quantize,
35434         dispatch: dispatch,
35435         dsvFormat: dsv,
35436         csvParse: csvParse,
35437         csvParseRows: csvParseRows,
35438         csvFormat: csvFormat,
35439         csvFormatRows: csvFormatRows,
35440         tsvParse: tsvParse,
35441         tsvParseRows: tsvParseRows,
35442         tsvFormat: tsvFormat,
35443         tsvFormatRows: tsvFormatRows,
35444         request: request,
35445         html: html,
35446         json: json,
35447         text: text,
35448         xml: xml,
35449         csv: csv$1,
35450         tsv: tsv$1,
35451         now: now,
35452         timer: timer,
35453         timerFlush: timerFlush,
35454         timeout: timeout$1,
35455         interval: interval$1,
35456         timeInterval: newInterval,
35457         timeMillisecond: millisecond,
35458         timeMilliseconds: milliseconds,
35459         timeSecond: second,
35460         timeSeconds: seconds,
35461         timeMinute: minute,
35462         timeMinutes: minutes,
35463         timeHour: hour,
35464         timeHours: hours,
35465         timeDay: day,
35466         timeDays: days,
35467         timeWeek: sunday,
35468         timeWeeks: sundays,
35469         timeSunday: sunday,
35470         timeSundays: sundays,
35471         timeMonday: monday,
35472         timeMondays: mondays,
35473         timeTuesday: tuesday,
35474         timeTuesdays: tuesdays,
35475         timeWednesday: wednesday,
35476         timeWednesdays: wednesdays,
35477         timeThursday: thursday,
35478         timeThursdays: thursdays,
35479         timeFriday: friday,
35480         timeFridays: fridays,
35481         timeSaturday: saturday,
35482         timeSaturdays: saturdays,
35483         timeMonth: month,
35484         timeMonths: months,
35485         timeYear: year,
35486         timeYears: years,
35487         utcMillisecond: millisecond,
35488         utcMilliseconds: milliseconds,
35489         utcSecond: second,
35490         utcSeconds: seconds,
35491         utcMinute: utcMinute,
35492         utcMinutes: utcMinutes,
35493         utcHour: utcHour,
35494         utcHours: utcHours,
35495         utcDay: utcDay,
35496         utcDays: utcDays,
35497         utcWeek: utcSunday,
35498         utcWeeks: utcSundays,
35499         utcSunday: utcSunday,
35500         utcSundays: utcSundays,
35501         utcMonday: utcMonday,
35502         utcMondays: utcMondays,
35503         utcTuesday: utcTuesday,
35504         utcTuesdays: utcTuesdays,
35505         utcWednesday: utcWednesday,
35506         utcWednesdays: utcWednesdays,
35507         utcThursday: utcThursday,
35508         utcThursdays: utcThursdays,
35509         utcFriday: utcFriday,
35510         utcFridays: utcFridays,
35511         utcSaturday: utcSaturday,
35512         utcSaturdays: utcSaturdays,
35513         utcMonth: utcMonth,
35514         utcMonths: utcMonths,
35515         utcYear: utcYear,
35516         utcYears: utcYears,
35517         get format () { return format; },
35518         get formatPrefix () { return formatPrefix; },
35519         formatLocale: formatLocale,
35520         formatDefaultLocale: defaultLocale,
35521         formatSpecifier: formatSpecifier,
35522         precisionFixed: precisionFixed,
35523         precisionPrefix: precisionPrefix,
35524         precisionRound: precisionRound,
35525         get timeFormat () { return timeFormat; },
35526         get timeParse () { return timeParse; },
35527         get utcFormat () { return utcFormat; },
35528         get utcParse () { return utcParse; },
35529         isoFormat: formatIso,
35530         isoParse: parseIso,
35531         timeFormatLocale: formatLocale$1,
35532         timeFormatDefaultLocale: defaultLocale$1,
35533         scaleBand: band,
35534         scalePoint: point$4,
35535         scaleIdentity: identity$4,
35536         scaleLinear: linear$2,
35537         scaleLog: log,
35538         scaleOrdinal: ordinal,
35539         scaleImplicit: implicit,
35540         scalePow: pow,
35541         scaleSqrt: sqrt,
35542         scaleQuantile: quantile$$1,
35543         scaleQuantize: quantize$1,
35544         scaleThreshold: threshold$1,
35545         scaleTime: time,
35546         scaleUtc: utcTime,
35547         schemeCategory10: category10,
35548         schemeCategory20b: category20b,
35549         schemeCategory20c: category20c,
35550         schemeCategory20: category20,
35551         scaleSequential: sequential,
35552         interpolateCubehelixDefault: cubehelix$3,
35553         interpolateRainbow: rainbow$1,
35554         interpolateWarm: warm,
35555         interpolateCool: cool,
35556         interpolateViridis: viridis,
35557         interpolateMagma: magma,
35558         interpolateInferno: inferno,
35559         interpolatePlasma: plasma,
35560         creator: creator,
35561         customEvent: customEvent,
35562         get event () { return event; },
35563         local: local,
35564         matcher: matcher$1,
35565         mouse: mouse,
35566         namespace: namespace,
35567         namespaces: namespaces,
35568         select: select,
35569         selectAll: selectAll,
35570         selection: selection,
35571         selector: selector,
35572         selectorAll: selectorAll,
35573         touch: touch,
35574         touches: touches,
35575         window: window$1,
35576         active: active,
35577         interrupt: interrupt,
35578         transition: transition,
35579         axisTop: axisTop,
35580         axisRight: axisRight,
35581         axisBottom: axisBottom,
35582         axisLeft: axisLeft,
35583         cluster: cluster,
35584         hierarchy: hierarchy,
35585         pack: index$2,
35586         packSiblings: siblings,
35587         packEnclose: enclose,
35588         partition: partition,
35589         stratify: stratify,
35590         tree: tree,
35591         treemap: index$3,
35592         treemapBinary: binary,
35593         treemapDice: treemapDice,
35594         treemapSlice: treemapSlice,
35595         treemapSliceDice: sliceDice,
35596         treemapSquarify: squarify,
35597         treemapResquarify: resquarify,
35598         forceCenter: center$1,
35599         forceCollide: collide,
35600         forceLink: link,
35601         forceManyBody: manyBody,
35602         forceSimulation: simulation,
35603         forceX: x$3,
35604         forceY: y$3,
35605         drag: drag,
35606         dragDisable: dragDisable,
35607         dragEnable: yesdrag,
35608         voronoi: voronoi,
35609         zoom: zoom,
35610         zoomIdentity: identity$6,
35611         zoomTransform: transform,
35612         brush: brush,
35613         brushX: brushX,
35614         brushY: brushY,
35615         brushSelection: brushSelection,
35616         chord: chord,
35617         ribbon: ribbon,
35618         geoAlbers: albers,
35619         geoAlbersUsa: albersUsa,
35620         geoArea: area$1,
35621         geoAzimuthalEqualArea: azimuthalEqualArea,
35622         geoAzimuthalEqualAreaRaw: azimuthalEqualAreaRaw,
35623         geoAzimuthalEquidistant: azimuthalEquidistant,
35624         geoAzimuthalEquidistantRaw: azimuthalEquidistantRaw,
35625         geoBounds: bounds,
35626         geoCentroid: d3GeoCentroid,
35627         geoCircle: circle$1,
35628         geoClipExtent: extent$1,
35629         geoConicConformal: conicConformal,
35630         geoConicConformalRaw: conicConformalRaw,
35631         geoConicEqualArea: conicEqualArea,
35632         geoConicEqualAreaRaw: conicEqualAreaRaw,
35633         geoConicEquidistant: conicEquidistant,
35634         geoConicEquidistantRaw: conicEquidistantRaw,
35635         geoDistance: distance,
35636         geoEquirectangular: equirectangular,
35637         geoEquirectangularRaw: equirectangularRaw,
35638         geoGnomonic: gnomonic,
35639         geoGnomonicRaw: gnomonicRaw,
35640         geoGraticule: graticule,
35641         geoGraticule10: graticule10,
35642         geoIdentity: identity$8,
35643         geoInterpolate: interpolate$2,
35644         geoLength: d3GeoLength,
35645         geoMercator: mercator,
35646         geoMercatorRaw: mercatorRaw,
35647         geoOrthographic: orthographic,
35648         geoOrthographicRaw: orthographicRaw,
35649         geoPath: index$5,
35650         geoProjection: projection,
35651         geoProjectionMutator: projectionMutator,
35652         geoRotation: rotation,
35653         geoStereographic: stereographic,
35654         geoStereographicRaw: stereographicRaw,
35655         geoStream: geoStream,
35656         geoTransform: transform$1,
35657         geoTransverseMercator: transverseMercator,
35658         geoTransverseMercatorRaw: transverseMercatorRaw
35659 });
35660
35661 /*
35662     Bypasses features of D3's default projection stream pipeline that are unnecessary:
35663     * Antimeridian clipping
35664     * Spherical rotation
35665     * Resampling
35666 */
35667 function geoRawMercator() {
35668     var project = mercatorRaw,
35669         k = 512 / Math.PI, // scale
35670         x = 0, y = 0, // translate
35671         clipExtent = [[0, 0], [0, 0]];
35672
35673
35674     function projection(point) {
35675         point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
35676         return [point[0] * k + x, y - point[1] * k];
35677     }
35678
35679
35680     projection.invert = function(point) {
35681         point = project.invert((point[0] - x) / k, (y - point[1]) / k);
35682         return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
35683     };
35684
35685
35686     projection.scale = function(_) {
35687         if (!arguments.length) return k;
35688         k = +_;
35689         return projection;
35690     };
35691
35692
35693     projection.translate = function(_) {
35694         if (!arguments.length) return [x, y];
35695         x = +_[0];
35696         y = +_[1];
35697         return projection;
35698     };
35699
35700
35701     projection.clipExtent = function(_) {
35702         if (!arguments.length) return clipExtent;
35703         clipExtent = _;
35704         return projection;
35705     };
35706
35707
35708     projection.transform = function(_) {
35709         if (!arguments.length) return identity$6.translate(x, y).scale(k);
35710         x = +_.x;
35711         y = +_.y;
35712         k = +_.k;
35713         return projection;
35714     };
35715
35716
35717     projection.stream = transform$1({
35718         point: function(x, y) {
35719             x = projection([x, y]);
35720             this.stream.point(x[0], x[1]);
35721         }
35722     }).stream;
35723
35724
35725     return projection;
35726 }
35727
35728 function geoRoundCoords(c) {
35729     return [Math.floor(c[0]), Math.floor(c[1])];
35730 }
35731
35732
35733 function geoInterp(p1, p2, t) {
35734     return [p1[0] + (p2[0] - p1[0]) * t,
35735             p1[1] + (p2[1] - p1[1]) * t];
35736 }
35737
35738
35739 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
35740 // Returns a positive value, if OAB makes a counter-clockwise turn,
35741 // negative for clockwise turn, and zero if the points are collinear.
35742 function geoCross(o, a, b) {
35743     return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
35744 }
35745
35746
35747 // http://jsperf.com/id-dist-optimization
35748 function geoEuclideanDistance(a, b) {
35749     var x = a[0] - b[0], y = a[1] - b[1];
35750     return Math.sqrt((x * x) + (y * y));
35751 }
35752
35753
35754 // using WGS84 polar radius (6356752.314245179 m)
35755 // const = 2 * PI * r / 360
35756 function geoLatToMeters(dLat) {
35757     return dLat * 110946.257617;
35758 }
35759
35760
35761 // using WGS84 equatorial radius (6378137.0 m)
35762 // const = 2 * PI * r / 360
35763 function geoLonToMeters(dLon, atLat) {
35764     return Math.abs(atLat) >= 90 ? 0 :
35765         dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
35766 }
35767
35768
35769 // using WGS84 polar radius (6356752.314245179 m)
35770 // const = 2 * PI * r / 360
35771 function geoMetersToLat(m) {
35772     return m / 110946.257617;
35773 }
35774
35775
35776 // using WGS84 equatorial radius (6378137.0 m)
35777 // const = 2 * PI * r / 360
35778 function geoMetersToLon(m, atLat) {
35779     return Math.abs(atLat) >= 90 ? 0 :
35780         m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
35781 }
35782
35783
35784 function geoOffsetToMeters(offset) {
35785     var equatRadius = 6356752.314245179,
35786         polarRadius = 6378137.0,
35787         tileSize = 256;
35788
35789     return [
35790         offset[0] * 2 * Math.PI * equatRadius / tileSize,
35791         -offset[1] * 2 * Math.PI * polarRadius / tileSize
35792     ];
35793 }
35794
35795
35796 function geoMetersToOffset(meters) {
35797     var equatRadius = 6356752.314245179,
35798         polarRadius = 6378137.0,
35799         tileSize = 256;
35800
35801     return [
35802         meters[0] * tileSize / (2 * Math.PI * equatRadius),
35803         -meters[1] * tileSize / (2 * Math.PI * polarRadius)
35804     ];
35805 }
35806
35807
35808 // Equirectangular approximation of spherical distances on Earth
35809 function geoSphericalDistance(a, b) {
35810     var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
35811         y = geoLatToMeters(a[1] - b[1]);
35812     return Math.sqrt((x * x) + (y * y));
35813 }
35814
35815
35816 function geoEdgeEqual(a, b) {
35817     return (a[0] === b[0] && a[1] === b[1]) ||
35818         (a[0] === b[1] && a[1] === b[0]);
35819 }
35820
35821
35822 // Return the counterclockwise angle in the range (-pi, pi)
35823 // between the positive X axis and the line intersecting a and b.
35824 function geoAngle(a, b, projection) {
35825     a = projection(a.loc);
35826     b = projection(b.loc);
35827     return Math.atan2(b[1] - a[1], b[0] - a[0]);
35828 }
35829
35830
35831 // Choose the edge with the minimal distance from `point` to its orthogonal
35832 // projection onto that edge, if such a projection exists, or the distance to
35833 // the closest vertex on that edge. Returns an object with the `index` of the
35834 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
35835 function geoChooseEdge(nodes, point, projection) {
35836     var dist = geoEuclideanDistance,
35837         points = nodes.map(function(n) { return projection(n.loc); }),
35838         min = Infinity,
35839         idx, loc;
35840
35841     function dot(p, q) {
35842         return p[0] * q[0] + p[1] * q[1];
35843     }
35844
35845     for (var i = 0; i < points.length - 1; i++) {
35846         var o = points[i],
35847             s = [points[i + 1][0] - o[0],
35848                  points[i + 1][1] - o[1]],
35849             v = [point[0] - o[0],
35850                  point[1] - o[1]],
35851             proj = dot(v, s) / dot(s, s),
35852             p;
35853
35854         if (proj < 0) {
35855             p = o;
35856         } else if (proj > 1) {
35857             p = points[i + 1];
35858         } else {
35859             p = [o[0] + proj * s[0], o[1] + proj * s[1]];
35860         }
35861
35862         var d = dist(p, point);
35863         if (d < min) {
35864             min = d;
35865             idx = i + 1;
35866             loc = projection.invert(p);
35867         }
35868     }
35869
35870     return {
35871         index: idx,
35872         distance: min,
35873         loc: loc
35874     };
35875 }
35876
35877
35878 // Return the intersection point of 2 line segments.
35879 // From https://github.com/pgkelley4/line-segments-intersect
35880 // This uses the vector cross product approach described below:
35881 //  http://stackoverflow.com/a/565282/786339
35882 function geoLineIntersection(a, b) {
35883     function subtractPoints(point1, point2) {
35884         return [point1[0] - point2[0], point1[1] - point2[1]];
35885     }
35886     function crossProduct(point1, point2) {
35887         return point1[0] * point2[1] - point1[1] * point2[0];
35888     }
35889
35890     var p = [a[0][0], a[0][1]],
35891         p2 = [a[1][0], a[1][1]],
35892         q = [b[0][0], b[0][1]],
35893         q2 = [b[1][0], b[1][1]],
35894         r = subtractPoints(p2, p),
35895         s = subtractPoints(q2, q),
35896         uNumerator = crossProduct(subtractPoints(q, p), r),
35897         denominator = crossProduct(r, s);
35898
35899     if (uNumerator && denominator) {
35900         var u = uNumerator / denominator,
35901             t = crossProduct(subtractPoints(q, p), s) / denominator;
35902
35903         if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
35904             return geoInterp(p, p2, t);
35905         }
35906     }
35907
35908     return null;
35909 }
35910
35911
35912 function geoPathIntersections(path1, path2) {
35913     var intersections = [];
35914     for (var i = 0; i < path1.length - 1; i++) {
35915         for (var j = 0; j < path2.length - 1; j++) {
35916             var a = [ path1[i], path1[i+1] ],
35917                 b = [ path2[j], path2[j+1] ],
35918                 hit = geoLineIntersection(a, b);
35919             if (hit) intersections.push(hit);
35920         }
35921     }
35922     return intersections;
35923 }
35924
35925
35926 // Return whether point is contained in polygon.
35927 //
35928 // `point` should be a 2-item array of coordinates.
35929 // `polygon` should be an array of 2-item arrays of coordinates.
35930 //
35931 // From https://github.com/substack/point-in-polygon.
35932 // ray-casting algorithm based on
35933 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
35934 //
35935 function geoPointInPolygon(point, polygon) {
35936     var x = point[0],
35937         y = point[1],
35938         inside = false;
35939
35940     for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
35941         var xi = polygon[i][0], yi = polygon[i][1];
35942         var xj = polygon[j][0], yj = polygon[j][1];
35943
35944         var intersect = ((yi > y) !== (yj > y)) &&
35945             (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
35946         if (intersect) inside = !inside;
35947     }
35948
35949     return inside;
35950 }
35951
35952
35953 function geoPolygonContainsPolygon(outer, inner) {
35954     return lodash.every(inner, function(point) {
35955         return geoPointInPolygon(point, outer);
35956     });
35957 }
35958
35959
35960 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
35961     function testSegments(outer, inner) {
35962         for (var i = 0; i < outer.length - 1; i++) {
35963             for (var j = 0; j < inner.length - 1; j++) {
35964                 var a = [ outer[i], outer[i+1] ],
35965                     b = [ inner[j], inner[j+1] ];
35966                 if (geoLineIntersection(a, b)) return true;
35967             }
35968         }
35969         return false;
35970     }
35971
35972     function testPoints(outer, inner) {
35973         return lodash.some(inner, function(point) {
35974             return geoPointInPolygon(point, outer);
35975         });
35976     }
35977
35978    return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
35979 }
35980
35981
35982 function geoPathLength(path) {
35983     var length = 0;
35984     for (var i = 0; i < path.length - 1; i++) {
35985         length += geoEuclideanDistance(path[i], path[i + 1]);
35986     }
35987     return length;
35988 }
35989
35990 function osmNode() {
35991     if (!(this instanceof osmNode)) {
35992         return (new osmNode()).initialize(arguments);
35993     } else if (arguments.length) {
35994         this.initialize(arguments);
35995     }
35996 }
35997
35998 osmEntity$$1.node = osmNode;
35999
36000 osmNode.prototype = Object.create(osmEntity$$1.prototype);
36001
36002 lodash.extend(osmNode.prototype, {
36003
36004     type: 'node',
36005
36006
36007     extent: function() {
36008         return new geoExtent$$1(this.loc);
36009     },
36010
36011
36012     geometry: function(graph) {
36013         return graph.transient(this, 'geometry', function() {
36014             return graph.isPoi(this) ? 'point' : 'vertex';
36015         });
36016     },
36017
36018
36019     move: function(loc) {
36020         return this.update({loc: loc});
36021     },
36022
36023
36024     isIntersection: function(resolver) {
36025         return resolver.transient(this, 'isIntersection', function() {
36026             return resolver.parentWays(this).filter(function(parent) {
36027                 return (parent.tags.highway ||
36028                     parent.tags.waterway ||
36029                     parent.tags.railway ||
36030                     parent.tags.aeroway) &&
36031                     parent.geometry(resolver) === 'line';
36032             }).length > 1;
36033         });
36034     },
36035
36036
36037     isHighwayIntersection: function(resolver) {
36038         return resolver.transient(this, 'isHighwayIntersection', function() {
36039             return resolver.parentWays(this).filter(function(parent) {
36040                 return parent.tags.highway && parent.geometry(resolver) === 'line';
36041             }).length > 1;
36042         });
36043     },
36044
36045
36046     isOnAddressLine: function(resolver) {
36047         return resolver.transient(this, 'isOnAddressLine', function() {
36048             return resolver.parentWays(this).filter(function(parent) {
36049                 return parent.tags.hasOwnProperty('addr:interpolation') &&
36050                     parent.geometry(resolver) === 'line';
36051             }).length > 0;
36052         });
36053     },
36054
36055
36056     asJXON: function(changeset_id) {
36057         var r = {
36058             node: {
36059                 '@id': this.osmId(),
36060                 '@lon': this.loc[0],
36061                 '@lat': this.loc[1],
36062                 '@version': (this.version || 0),
36063                 tag: lodash.map(this.tags, function(v, k) {
36064                     return { keyAttributes: { k: k, v: v } };
36065                 })
36066             }
36067         };
36068         if (changeset_id) r.node['@changeset'] = changeset_id;
36069         return r;
36070     },
36071
36072
36073     asGeoJSON: function() {
36074         return {
36075             type: 'Point',
36076             coordinates: this.loc
36077         };
36078     }
36079 });
36080
36081 /*
36082   Order the nodes of a way in reverse order and reverse any direction dependent tags
36083   other than `oneway`. (We assume that correcting a backwards oneway is the primary
36084   reason for reversing a way.)
36085
36086   The following transforms are performed:
36087
36088     Keys:
36089           *:right=* ⟺ *:left=*
36090         *:forward=* ⟺ *:backward=*
36091        direction=up ⟺ direction=down
36092          incline=up ⟺ incline=down
36093             *=right ⟺ *=left
36094
36095     Relation members:
36096        role=forward ⟺ role=backward
36097          role=north ⟺ role=south
36098           role=east ⟺ role=west
36099
36100    In addition, numeric-valued `incline` tags are negated.
36101
36102    The JOSM implementation was used as a guide, but transformations that were of unclear benefit
36103    or adjusted tags that don't seem to be used in practice were omitted.
36104
36105    Also, each node on the way is examined for its own tags and the following transformations are performed
36106    in order to ensure associated nodes (eg a Stop Sign) is also reversed
36107
36108     Node Keys:
36109         direction=forward ⟺ direction=backward
36110         direction=left ⟺ direction=right
36111         *:forward=* ⟺ *:backward=*
36112         *:left=* ⟺ *:right=*
36113
36114    References:
36115       http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
36116       http://wiki.openstreetmap.org/wiki/Key:direction#Steps
36117       http://wiki.openstreetmap.org/wiki/Key:incline
36118       http://wiki.openstreetmap.org/wiki/Route#Members
36119       http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
36120       http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
36121       http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
36122  */
36123 function actionReverse(wayId, options) {
36124     var replacements = [
36125             [/:right$/, ':left'], [/:left$/, ':right'],
36126             [/:forward$/, ':backward'], [/:backward$/, ':forward']
36127         ],
36128         numeric = /^([+\-]?)(?=[\d.])/,
36129         roleReversals = {
36130             forward: 'backward',
36131             backward: 'forward',
36132             north: 'south',
36133             south: 'north',
36134             east: 'west',
36135             west: 'east'
36136         };
36137
36138
36139     function reverseKey(key) {
36140         for (var i = 0; i < replacements.length; ++i) {
36141             var replacement = replacements[i];
36142             if (replacement[0].test(key)) {
36143                 return key.replace(replacement[0], replacement[1]);
36144             }
36145         }
36146         return key;
36147     }
36148
36149
36150     function reverseValue(key, value) {
36151         if (key === 'incline' && numeric.test(value)) {
36152             return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
36153         } else if (key === 'incline' || key === 'direction') {
36154             return {up: 'down', down: 'up'}[value] || value;
36155         } else if (options && options.reverseOneway && key === 'oneway') {
36156             return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
36157         } else {
36158             return {left: 'right', right: 'left'}[value] || value;
36159         }
36160     }
36161
36162
36163     function reverseDirectionTags(node) {
36164         // Update the direction based tags as appropriate then return an updated node
36165         return node.update({tags: lodash.transform(node.tags, function(acc, tagValue, tagKey) {
36166             // See if this is a direction tag and reverse (or use existing value if not recognised)
36167             if (tagKey === 'direction') {
36168                 acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
36169             } else {
36170                 // Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
36171                 // This will pass through other tags unchanged
36172                 acc[reverseKey(tagKey)] = tagValue;
36173             }
36174             return acc;
36175         }, {})});
36176     }
36177
36178
36179     function reverseTagsOnNodes(graph, nodeIds) {
36180         // Reverse the direction of appropriate tags attached to the nodes (#3076)
36181         return lodash(nodeIds)
36182             // Get each node from the graph
36183             .map(function(nodeId) { return graph.entity(nodeId);})
36184             // Check tags on the node, if there aren't any, we can skip
36185             .filter(function(existingNode) { return existingNode.tags !== undefined;})
36186             // Get a new version of each node with the appropriate tags reversed
36187             .map(function(existingNode) { return reverseDirectionTags(existingNode);})
36188             // Chain together consecutive updates to the graph for each updated node and return
36189             .reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
36190     }
36191
36192
36193     return function(graph) {
36194         var way = graph.entity(wayId),
36195             nodes = way.nodes.slice().reverse(),
36196             tags = {}, key, role;
36197
36198         for (key in way.tags) {
36199             tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
36200         }
36201
36202         graph.parentRelations(way).forEach(function(relation) {
36203             relation.members.forEach(function(member, index) {
36204                 if (member.id === way.id && (role = roleReversals[member.role])) {
36205                     relation = relation.updateMember({role: role}, index);
36206                     graph = graph.replace(relation);
36207                 }
36208             });
36209         });
36210
36211         // Reverse any associated directions on nodes on the way and then replace
36212         // the way itself with the reversed node ids and updated way tags
36213         return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
36214     };
36215 }
36216
36217 // For fixing up rendering of multipolygons with tags on the outer member.
36218 // https://github.com/openstreetmap/iD/issues/613
36219 function osmIsSimpleMultipolygonOuterMember(entity, graph) {
36220     if (entity.type !== 'way')
36221         return false;
36222
36223     var parents = graph.parentRelations(entity);
36224     if (parents.length !== 1)
36225         return false;
36226
36227     var parent = parents[0];
36228     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36229         return false;
36230
36231     var members = parent.members, member;
36232     for (var i = 0; i < members.length; i++) {
36233         member = members[i];
36234         if (member.id === entity.id && member.role && member.role !== 'outer')
36235             return false; // Not outer member
36236         if (member.id !== entity.id && (!member.role || member.role === 'outer'))
36237             return false; // Not a simple multipolygon
36238     }
36239
36240     return parent;
36241 }
36242
36243
36244 function osmSimpleMultipolygonOuterMember(entity, graph) {
36245     if (entity.type !== 'way')
36246         return false;
36247
36248     var parents = graph.parentRelations(entity);
36249     if (parents.length !== 1)
36250         return false;
36251
36252     var parent = parents[0];
36253     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36254         return false;
36255
36256     var members = parent.members, member, outerMember;
36257     for (var i = 0; i < members.length; i++) {
36258         member = members[i];
36259         if (!member.role || member.role === 'outer') {
36260             if (outerMember)
36261                 return false; // Not a simple multipolygon
36262             outerMember = member;
36263         }
36264     }
36265
36266     return outerMember && graph.hasEntity(outerMember.id);
36267 }
36268
36269
36270 // Join `array` into sequences of connecting ways.
36271 //
36272 // Segments which share identical start/end nodes will, as much as possible,
36273 // be connected with each other.
36274 //
36275 // The return value is a nested array. Each constituent array contains elements
36276 // of `array` which have been determined to connect. Each consitituent array
36277 // also has a `nodes` property whose value is an ordered array of member nodes,
36278 // with appropriate order reversal and start/end coordinate de-duplication.
36279 //
36280 // Members of `array` must have, at minimum, `type` and `id` properties.
36281 // Thus either an array of `osmWay`s or a relation member array may be
36282 // used.
36283 //
36284 // If an member has a `tags` property, its tags will be reversed via
36285 // `actionReverse` in the output.
36286 //
36287 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
36288 // false) and non-way members are ignored.
36289 //
36290 function osmJoinWays(array, graph) {
36291     var joined = [], member, current, nodes, first, last, i, how, what;
36292
36293     array = array.filter(function(member) {
36294         return member.type === 'way' && graph.hasEntity(member.id);
36295     });
36296
36297     function resolve(member) {
36298         return graph.childNodes(graph.entity(member.id));
36299     }
36300
36301     function reverse(member) {
36302         return member.tags ? actionReverse(member.id, { reverseOneway: true })(graph).entity(member.id) : member;
36303     }
36304
36305     while (array.length) {
36306         member = array.shift();
36307         current = [member];
36308         current.nodes = nodes = resolve(member).slice();
36309         joined.push(current);
36310
36311         while (array.length && lodash.first(nodes) !== lodash.last(nodes)) {
36312             first = lodash.first(nodes);
36313             last  = lodash.last(nodes);
36314
36315             for (i = 0; i < array.length; i++) {
36316                 member = array[i];
36317                 what = resolve(member);
36318
36319                 if (last === lodash.first(what)) {
36320                     how  = nodes.push;
36321                     what = what.slice(1);
36322                     break;
36323                 } else if (last === lodash.last(what)) {
36324                     how  = nodes.push;
36325                     what = what.slice(0, -1).reverse();
36326                     member = reverse(member);
36327                     break;
36328                 } else if (first === lodash.last(what)) {
36329                     how  = nodes.unshift;
36330                     what = what.slice(0, -1);
36331                     break;
36332                 } else if (first === lodash.first(what)) {
36333                     how  = nodes.unshift;
36334                     what = what.slice(1).reverse();
36335                     member = reverse(member);
36336                     break;
36337                 } else {
36338                     what = how = null;
36339                 }
36340             }
36341
36342             if (!what)
36343                 break; // No more joinable ways.
36344
36345             how.apply(current, [member]);
36346             how.apply(nodes, what);
36347
36348             array.splice(i, 1);
36349         }
36350     }
36351
36352     return joined;
36353 }
36354
36355 function osmRelation() {
36356     if (!(this instanceof osmRelation)) {
36357         return (new osmRelation()).initialize(arguments);
36358     } else if (arguments.length) {
36359         this.initialize(arguments);
36360     }
36361 }
36362
36363
36364 osmEntity$$1.relation = osmRelation;
36365
36366 osmRelation.prototype = Object.create(osmEntity$$1.prototype);
36367
36368
36369 osmRelation.creationOrder = function(a, b) {
36370     var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10);
36371     var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10);
36372
36373     if (aId < 0 || bId < 0) return aId - bId;
36374     return bId - aId;
36375 };
36376
36377
36378 lodash.extend(osmRelation.prototype, {
36379     type: 'relation',
36380     members: [],
36381
36382
36383     copy: function(resolver, copies) {
36384         if (copies[this.id])
36385             return copies[this.id];
36386
36387         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
36388
36389         var members = this.members.map(function(member) {
36390             return lodash.extend({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
36391         });
36392
36393         copy = copy.update({members: members});
36394         copies[this.id] = copy;
36395
36396         return copy;
36397     },
36398
36399
36400     extent: function(resolver, memo) {
36401         return resolver.transient(this, 'extent', function() {
36402             if (memo && memo[this.id]) return geoExtent$$1();
36403             memo = memo || {};
36404             memo[this.id] = true;
36405
36406             var extent$$1 = geoExtent$$1();
36407             for (var i = 0; i < this.members.length; i++) {
36408                 var member = resolver.hasEntity(this.members[i].id);
36409                 if (member) {
36410                     extent$$1._extend(member.extent(resolver, memo));
36411                 }
36412             }
36413             return extent$$1;
36414         });
36415     },
36416
36417
36418     geometry: function(graph) {
36419         return graph.transient(this, 'geometry', function() {
36420             return this.isMultipolygon() ? 'area' : 'relation';
36421         });
36422     },
36423
36424
36425     isDegenerate: function() {
36426         return this.members.length === 0;
36427     },
36428
36429
36430     // Return an array of members, each extended with an 'index' property whose value
36431     // is the member index.
36432     indexedMembers: function() {
36433         var result = new Array(this.members.length);
36434         for (var i = 0; i < this.members.length; i++) {
36435             result[i] = lodash.extend({}, this.members[i], {index: i});
36436         }
36437         return result;
36438     },
36439
36440
36441     // Return the first member with the given role. A copy of the member object
36442     // is returned, extended with an 'index' property whose value is the member index.
36443     memberByRole: function(role) {
36444         for (var i = 0; i < this.members.length; i++) {
36445             if (this.members[i].role === role) {
36446                 return lodash.extend({}, this.members[i], {index: i});
36447             }
36448         }
36449     },
36450
36451
36452     // Return the first member with the given id. A copy of the member object
36453     // is returned, extended with an 'index' property whose value is the member index.
36454     memberById: function(id) {
36455         for (var i = 0; i < this.members.length; i++) {
36456             if (this.members[i].id === id) {
36457                 return lodash.extend({}, this.members[i], {index: i});
36458             }
36459         }
36460     },
36461
36462
36463     // Return the first member with the given id and role. A copy of the member object
36464     // is returned, extended with an 'index' property whose value is the member index.
36465     memberByIdAndRole: function(id, role) {
36466         for (var i = 0; i < this.members.length; i++) {
36467             if (this.members[i].id === id && this.members[i].role === role) {
36468                 return lodash.extend({}, this.members[i], {index: i});
36469             }
36470         }
36471     },
36472
36473
36474     addMember: function(member, index) {
36475         var members = this.members.slice();
36476         members.splice(index === undefined ? members.length : index, 0, member);
36477         return this.update({members: members});
36478     },
36479
36480
36481     updateMember: function(member, index) {
36482         var members = this.members.slice();
36483         members.splice(index, 1, lodash.extend({}, members[index], member));
36484         return this.update({members: members});
36485     },
36486
36487
36488     removeMember: function(index) {
36489         var members = this.members.slice();
36490         members.splice(index, 1);
36491         return this.update({members: members});
36492     },
36493
36494
36495     removeMembersWithID: function(id) {
36496         var members = lodash.reject(this.members, function(m) { return m.id === id; });
36497         return this.update({members: members});
36498     },
36499
36500
36501     // Wherever a member appears with id `needle.id`, replace it with a member
36502     // with id `replacement.id`, type `replacement.type`, and the original role,
36503     // unless a member already exists with that id and role. Return an updated
36504     // relation.
36505     replaceMember: function(needle, replacement) {
36506         if (!this.memberById(needle.id))
36507             return this;
36508
36509         var members = [];
36510
36511         for (var i = 0; i < this.members.length; i++) {
36512             var member = this.members[i];
36513             if (member.id !== needle.id) {
36514                 members.push(member);
36515             } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
36516                 members.push({id: replacement.id, type: replacement.type, role: member.role});
36517             }
36518         }
36519
36520         return this.update({members: members});
36521     },
36522
36523
36524     asJXON: function(changeset_id) {
36525         var r = {
36526             relation: {
36527                 '@id': this.osmId(),
36528                 '@version': this.version || 0,
36529                 member: lodash.map(this.members, function(member) {
36530                     return {
36531                         keyAttributes: {
36532                             type: member.type,
36533                             role: member.role,
36534                             ref: osmEntity$$1.id.toOSM(member.id)
36535                         }
36536                     };
36537                 }),
36538                 tag: lodash.map(this.tags, function(v, k) {
36539                     return { keyAttributes: { k: k, v: v } };
36540                 })
36541             }
36542         };
36543         if (changeset_id) r.relation['@changeset'] = changeset_id;
36544         return r;
36545     },
36546
36547
36548     asGeoJSON: function(resolver) {
36549         return resolver.transient(this, 'GeoJSON', function () {
36550             if (this.isMultipolygon()) {
36551                 return {
36552                     type: 'MultiPolygon',
36553                     coordinates: this.multipolygon(resolver)
36554                 };
36555             } else {
36556                 return {
36557                     type: 'FeatureCollection',
36558                     properties: this.tags,
36559                     features: this.members.map(function (member) {
36560                         return lodash.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
36561                     })
36562                 };
36563             }
36564         });
36565     },
36566
36567
36568     area: function(resolver) {
36569         return resolver.transient(this, 'area', function() {
36570             return area$1(this.asGeoJSON(resolver));
36571         });
36572     },
36573
36574
36575     isMultipolygon: function() {
36576         return this.tags.type === 'multipolygon';
36577     },
36578
36579
36580     isComplete: function(resolver) {
36581         for (var i = 0; i < this.members.length; i++) {
36582             if (!resolver.hasEntity(this.members[i].id)) {
36583                 return false;
36584             }
36585         }
36586         return true;
36587     },
36588
36589
36590     isRestriction: function() {
36591         return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
36592     },
36593
36594
36595     // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
36596     // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
36597     //
36598     // This corresponds to the structure needed for rendering a multipolygon path using a
36599     // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
36600     //
36601     // In the case of invalid geometries, this function will still return a result which
36602     // includes the nodes of all way members, but some Nds may be unclosed and some inner
36603     // rings not matched with the intended outer ring.
36604     //
36605     multipolygon: function(resolver) {
36606         var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
36607             inners = this.members.filter(function(m) { return 'inner' === m.role; });
36608
36609         outers = osmJoinWays(outers, resolver);
36610         inners = osmJoinWays(inners, resolver);
36611
36612         outers = outers.map(function(outer) { return lodash.map(outer.nodes, 'loc'); });
36613         inners = inners.map(function(inner) { return lodash.map(inner.nodes, 'loc'); });
36614
36615         var result = outers.map(function(o) {
36616             // Heuristic for detecting counterclockwise winding order. Assumes
36617             // that OpenStreetMap polygons are not hemisphere-spanning.
36618             return [area$1({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o];
36619         });
36620
36621         function findOuter(inner) {
36622             var o, outer;
36623
36624             for (o = 0; o < outers.length; o++) {
36625                 outer = outers[o];
36626                 if (geoPolygonContainsPolygon(outer, inner))
36627                     return o;
36628             }
36629
36630             for (o = 0; o < outers.length; o++) {
36631                 outer = outers[o];
36632                 if (geoPolygonIntersectsPolygon(outer, inner, false))
36633                     return o;
36634             }
36635         }
36636
36637         for (var i = 0; i < inners.length; i++) {
36638             var inner = inners[i];
36639
36640             if (area$1({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) {
36641                 inner = inner.reverse();
36642             }
36643
36644             var o = findOuter(inners[i]);
36645             if (o !== undefined)
36646                 result[o].push(inners[i]);
36647             else
36648                 result.push([inners[i]]); // Invalid geometry
36649         }
36650
36651         return result;
36652     }
36653 });
36654
36655 function osmLanes(entity) {
36656     if (entity.type !== 'way') return null;
36657     if (!entity.tags.highway) return null;
36658
36659     var tags = entity.tags;
36660     var isOneWay = entity.isOneWay();
36661     var laneCount = getLaneCount(tags, isOneWay);
36662     var maxspeed = parseMaxspeed(tags);
36663
36664     var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
36665     var forward = laneDirections.forward;
36666     var backward = laneDirections.backward;
36667     var bothways = laneDirections.bothways;
36668
36669     // parse the piped string 'x|y|z' format
36670     var turnLanes = {};
36671     turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
36672     turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
36673     turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
36674
36675     var maxspeedLanes = {};
36676     maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
36677     maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
36678     maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
36679
36680     var psvLanes = {};
36681     psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
36682     psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
36683     psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
36684
36685     var busLanes = {};
36686     busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
36687     busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
36688     busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
36689
36690     var taxiLanes = {};
36691     taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
36692     taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
36693     taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
36694
36695     var hovLanes = {};
36696     hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
36697     hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
36698     hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
36699
36700     var hgvLanes = {};
36701     hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
36702     hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
36703     hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
36704
36705     var bicyclewayLanes = {};
36706     bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
36707     bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
36708     bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
36709
36710     var lanesObj = {
36711         forward: [],
36712         backward: [],
36713         unspecified: []
36714     };
36715
36716     // map forward/backward/unspecified of each lane type to lanesObj
36717     mapToLanesObj(lanesObj, turnLanes, 'turnLane');
36718     mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
36719     mapToLanesObj(lanesObj, psvLanes, 'psv');
36720     mapToLanesObj(lanesObj, busLanes, 'bus');
36721     mapToLanesObj(lanesObj, taxiLanes, 'taxi');
36722     mapToLanesObj(lanesObj, hovLanes, 'hov');
36723     mapToLanesObj(lanesObj, hgvLanes, 'hgv');
36724     mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
36725
36726     return {
36727         metadata: {
36728             count: laneCount,
36729             oneway: isOneWay,
36730             forward: forward,
36731             backward: backward,
36732             bothways: bothways,
36733             turnLanes: turnLanes,
36734             maxspeed: maxspeed,
36735             maxspeedLanes: maxspeedLanes,
36736             psvLanes: psvLanes,
36737             busLanes: busLanes,
36738             taxiLanes: taxiLanes,
36739             hovLanes: hovLanes,
36740             hgvLanes: hgvLanes,
36741             bicyclewayLanes: bicyclewayLanes
36742         },
36743         lanes: lanesObj
36744     };
36745 }
36746
36747
36748 function getLaneCount(tags, isOneWay) {
36749     var count;
36750     if (tags.lanes) {
36751         count = parseInt(tags.lanes, 10);
36752         if (count > 0) {
36753             return count;
36754         }
36755     }
36756
36757
36758     switch (tags.highway) {
36759         case 'trunk':
36760         case 'motorway':
36761             count = isOneWay ? 2 : 4;
36762             break;
36763         default:
36764             count = isOneWay ? 1 : 2;
36765             break;
36766     }
36767
36768     return count;
36769 }
36770
36771
36772 function parseMaxspeed(tags) {
36773     var maxspeed = tags.maxspeed;
36774     if (lodash.isNumber(maxspeed)) return maxspeed;
36775     if (lodash.isString(maxspeed)) {
36776         maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g);
36777         if (!maxspeed) return;
36778         return parseInt(maxspeed, 10);
36779     }
36780 }
36781
36782
36783 function parseLaneDirections(tags, isOneWay, laneCount) {
36784     var forward = parseInt(tags['lanes:forward'], 10);
36785     var backward = parseInt(tags['lanes:backward'], 10);
36786     var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
36787
36788     if (parseInt(tags.oneway, 10) === -1) {
36789         forward = 0;
36790         bothways = 0;
36791         backward = laneCount;
36792     }
36793     else if (isOneWay) {
36794         forward = laneCount;
36795         bothways = 0;
36796         backward = 0;
36797     }
36798     else if (lodash.isNaN(forward) && lodash.isNaN(backward)) {
36799         backward = Math.floor((laneCount - bothways) / 2);
36800         forward = laneCount - bothways - backward;
36801     }
36802     else if (lodash.isNaN(forward)) {
36803         if (backward > laneCount - bothways) {
36804             backward = laneCount - bothways;
36805         }
36806         forward = laneCount - bothways - backward;
36807     }
36808     else if (lodash.isNaN(backward)) {
36809         if (forward > laneCount - bothways) {
36810             forward = laneCount - bothways;
36811         }
36812         backward = laneCount - bothways - forward;
36813     }
36814     return {
36815         forward: forward,
36816         backward: backward,
36817         bothways: bothways
36818     };
36819 }
36820
36821
36822 function parseTurnLanes(tag){
36823     if (!tag) return;
36824
36825     var validValues = [
36826         'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right',
36827         'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'
36828     ];
36829
36830     return tag.split('|')
36831         .map(function (s) {
36832             if (s === '') s = 'none';
36833             return s.split(';')
36834                 .map(function (d) {
36835                     return validValues.indexOf(d) === -1 ? 'unknown': d;
36836                 });
36837         });
36838 }
36839
36840
36841 function parseMaxspeedLanes(tag, maxspeed) {
36842     if (!tag) return;
36843
36844     return tag.split('|')
36845         .map(function (s) {
36846             if (s === 'none') return s;
36847             var m = parseInt(s, 10);
36848             if (s === '' || m === maxspeed) return null;
36849             return lodash.isNaN(m) ? 'unknown': m;
36850         });
36851 }
36852
36853
36854 function parseMiscLanes(tag) {
36855     if (!tag) return;
36856
36857     var validValues = [
36858         'yes', 'no', 'designated'
36859     ];
36860
36861     return tag.split('|')
36862         .map(function (s) {
36863             if (s === '') s = 'no';
36864             return validValues.indexOf(s) === -1 ? 'unknown': s;
36865         });
36866 }
36867
36868
36869 function parseBicycleWay(tag) {
36870     if (!tag) return;
36871
36872     var validValues = [
36873         'yes', 'no', 'designated', 'lane'
36874     ];
36875
36876     return tag.split('|')
36877         .map(function (s) {
36878             if (s === '') s = 'no';
36879             return validValues.indexOf(s) === -1 ? 'unknown': s;
36880         });
36881 }
36882
36883
36884 function mapToLanesObj(lanesObj, data, key) {
36885     if (data.forward) data.forward.forEach(function(l, i) {
36886         if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
36887         lanesObj.forward[i][key] = l;
36888     });
36889     if (data.backward) data.backward.forEach(function(l, i) {
36890         if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
36891         lanesObj.backward[i][key] = l;
36892     });
36893     if (data.unspecified) data.unspecified.forEach(function(l, i) {
36894         if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
36895         lanesObj.unspecified[i][key] = l;
36896     });
36897 }
36898
36899 var translations = Object.create(null);
36900
36901 var currentLocale = 'en';
36902 var textDirection = 'ltr';
36903
36904 function setLocale(_) {
36905     if (translations[_] !== undefined) {
36906         currentLocale = _;
36907     } else if (translations[_.split('-')[0]]) {
36908         currentLocale = _.split('-')[0];
36909     }
36910 }
36911
36912 function addTranslation(id, value) {
36913     translations[id] = value;
36914 }
36915
36916 /**
36917  * Given a string identifier, try to find that string in the current
36918  * language, and return it.
36919  *
36920  * @param {string} s string identifier
36921  * @returns {string?} locale string
36922  */
36923 function t(s, o, loc) {
36924     loc = loc || currentLocale;
36925
36926     var path = s.split('.').reverse();
36927     var rep = translations[loc];
36928
36929     while (rep !== undefined && path.length) rep = rep[path.pop()];
36930
36931     if (rep !== undefined) {
36932         if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
36933         return rep;
36934     }
36935
36936     if (loc !== 'en') {
36937         return t(s, o, 'en');
36938     }
36939
36940     if (o && 'default' in o) {
36941         return o.default;
36942     }
36943
36944     var missing = 'Missing ' + loc + ' translation: ' + s;
36945     if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
36946
36947     return missing;
36948 }
36949
36950 /**
36951  * Given string 'ltr' or 'rtl', save that setting
36952  *
36953  * @param {string} s ltr or rtl
36954  */
36955
36956 function setTextDirection(dir) {
36957     textDirection = dir;
36958 }
36959
36960 var detected;
36961
36962 function utilDetect(force) {
36963     if (detected && !force) return detected;
36964     detected = {};
36965
36966     var ua = navigator.userAgent,
36967         m = null;
36968
36969     m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i);   // Edge
36970     if (m !== null) {
36971         detected.browser = m[1];
36972         detected.version = m[2];
36973     }
36974     if (!detected.browser) {
36975         m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i);   // IE11
36976         if (m !== null) {
36977             detected.browser = 'msie';
36978             detected.version = m[1];
36979         }
36980     }
36981     if (!detected.browser) {
36982         m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i);   // Opera 15+
36983         if (m !== null) {
36984             detected.browser = 'Opera';
36985             detected.version = m[2];
36986         }
36987     }
36988     if (!detected.browser) {
36989         m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
36990         if (m !== null) {
36991             detected.browser = m[1];
36992             detected.version = m[2];
36993             m = ua.match(/version\/([\.\d]+)/i);
36994             if (m !== null) detected.version = m[1];
36995         }
36996     }
36997     if (!detected.browser) {
36998         detected.browser = navigator.appName;
36999         detected.version = navigator.appVersion;
37000     }
37001
37002     // keep major.minor version only..
37003     detected.version = detected.version.split(/\W/).slice(0,2).join('.');
37004
37005     if (detected.browser.toLowerCase() === 'msie') {
37006         detected.ie = true;
37007         detected.browser = 'Internet Explorer';
37008         detected.support = parseFloat(detected.version) >= 11;
37009     } else {
37010         detected.ie = false;
37011         detected.support = true;
37012     }
37013
37014     // Added due to incomplete svg style support. See #715
37015     detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
37016
37017     detected.locale = (navigator.languages && navigator.languages.length)
37018         ? navigator.languages[0] : (navigator.language || navigator.userLanguage || 'en-US');
37019
37020     // Loaded locale is stored in currentLocale
37021     // return that instead (except in the situation where 'en' might override 'en-US')
37022     var loadedLocale = currentLocale || 'en';
37023     if (loadedLocale !== 'en') {
37024         detected.locale = loadedLocale;
37025     }
37026
37027     // detect text direction
37028     var q = utilStringQs(window.location.hash.substring(1));
37029     var lang = dataLocales[detected.locale];
37030     if ((lang && lang.rtl) || 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 lowZoom = context.surface().classed('low-zoom');
42652
42653         var labelable = [], i, j, k, entity, geometry;
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             geometry = entity.geometry(graph);
42680             if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
42681
42682             var preset = geometry === 'area' && context.presets().match(entity, graph),
42683                 icon = preset && !blacklisted(preset) && preset.icon;
42684
42685             if (!icon && !utilDisplayName(entity))
42686                 continue;
42687
42688             for (k = 0; k < labelStack.length; k++) {
42689                 var matchGeom = labelStack[k][0],
42690                     matchKey = labelStack[k][1],
42691                     matchVal = labelStack[k][2],
42692                     hasVal = entity.tags[matchKey];
42693
42694                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
42695                     labelable[k].push(entity);
42696                     break;
42697                 }
42698             }
42699         }
42700
42701         var positions = {
42702             point: [],
42703             line: [],
42704             area: []
42705         };
42706
42707         var labelled = {
42708             point: [],
42709             line: [],
42710             area: []
42711         };
42712
42713         // Try and find a valid label for labellable entities
42714         for (k = 0; k < labelable.length; k++) {
42715             var fontSize = labelStack[k][3];
42716             for (i = 0; i < labelable[k].length; i++) {
42717                 entity = labelable[k][i];
42718                 geometry = entity.geometry(graph);
42719
42720                 var name = utilDisplayName(entity),
42721                     width = name && textWidth(name, fontSize),
42722                     p;
42723                 if (geometry === 'point') {
42724                     p = getPointLabel(entity, width, fontSize, geometry);
42725                 } else if (geometry === 'vertex' && !lowZoom) {
42726                     // don't label vertices at low zoom because they don't have icons
42727                     p = getPointLabel(entity, width, fontSize, geometry);
42728                 } else if (geometry === 'line') {
42729                     p = getLineLabel(entity, width, fontSize);
42730                 } else if (geometry === 'area') {
42731                     p = getAreaLabel(entity, width, fontSize);
42732                 }
42733
42734                 if (p) {
42735                     if (geometry === 'vertex') { geometry = 'point'; }  // treat vertex like point
42736                     p.classes = geometry + ' tag-' + labelStack[k][1];
42737                     positions[geometry].push(p);
42738                     labelled[geometry].push(entity);
42739                 }
42740             }
42741         }
42742
42743
42744         function getPointLabel(entity, width, height, geometry) {
42745             var y = (geometry === 'point' ? -12 : 0),
42746                 pointOffsets = {
42747                     ltr: [15, y, 'start'],
42748                     rtl: [-15, y, 'end']
42749                 };
42750
42751             var coord = projection(entity.loc),
42752                 margin = 2,
42753                 textDirection = detected.textDirection,
42754                 offset = pointOffsets[textDirection],
42755                 p = {
42756                     height: height,
42757                     width: width,
42758                     x: coord[0] + offset[0],
42759                     y: coord[1] + offset[1],
42760                     textAnchor: offset[2]
42761                 },
42762                 bbox;
42763
42764             if (textDirection === 'rtl') {
42765                 bbox = {
42766                     minX: p.x - width - margin,
42767                     minY: p.y - (height / 2) - margin,
42768                     maxX: p.x + margin,
42769                     maxY: p.y + (height / 2) + margin
42770                 };
42771             } else {
42772                 bbox = {
42773                     minX: p.x - margin,
42774                     minY: p.y - (height / 2) - margin,
42775                     maxX: p.x + width + margin,
42776                     maxY: p.y + (height / 2) + margin
42777                 };
42778             }
42779
42780             if (tryInsert([bbox], entity.id, true)) {
42781                 return p;
42782             }
42783         }
42784
42785
42786         function getLineLabel(entity, width, height) {
42787             var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
42788                 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
42789                 length = geoPathLength(nodes);
42790
42791             if (length < width + 20) return;
42792
42793             // % along the line to attempt to place the label
42794             var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
42795                                25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
42796             var margin = 3;
42797
42798             for (var i = 0; i < lineOffsets.length; i++) {
42799                 var offset = lineOffsets[i],
42800                     middle = offset / 100 * length,
42801                     start = middle - width / 2;
42802
42803                 if (start < 0 || start + width > length) continue;
42804
42805                 // generate subpath and ignore paths that are invalid or don't cross viewport.
42806                 var sub = subpath(nodes, start, start + width);
42807                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
42808                     continue;
42809                 }
42810
42811                 var isReverse = reverse(sub);
42812                 if (isReverse) {
42813                     sub = sub.reverse();
42814                 }
42815
42816                 var bboxes = [],
42817                     boxsize = (height + 2) / 2;
42818
42819                 for (var j = 0; j < sub.length - 1; j++) {
42820                     var a = sub[j];
42821                     var b = sub[j + 1];
42822                     var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
42823
42824                     for (var box = 0; box < num; box++) {
42825                         var p = geoInterp(a, b, box / num);
42826                         var x0 = p[0] - boxsize - margin;
42827                         var y0 = p[1] - boxsize - margin;
42828                         var x1 = p[0] + boxsize + margin;
42829                         var y1 = p[1] + boxsize + margin;
42830
42831                         bboxes.push({
42832                             minX: Math.min(x0, x1),
42833                             minY: Math.min(y0, y1),
42834                             maxX: Math.max(x0, x1),
42835                             maxY: Math.max(y0, y1)
42836                         });
42837                     }
42838                 }
42839
42840                 if (tryInsert(bboxes, entity.id, false)) {
42841                     return {
42842                         'font-size': height + 2,
42843                         lineString: lineString(sub),
42844                         startOffset: offset + '%'
42845                     };
42846                 }
42847             }
42848
42849             function reverse(p) {
42850                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
42851                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
42852             }
42853
42854             function lineString(nodes) {
42855                 return 'M' + nodes.join('L');
42856             }
42857
42858             function subpath(nodes, from, to) {
42859                 var sofar = 0,
42860                     start, end, i0, i1;
42861
42862                 for (var i = 0; i < nodes.length - 1; i++) {
42863                     var a = nodes[i],
42864                         b = nodes[i + 1];
42865                     var current = geoEuclideanDistance(a, b);
42866                     var portion;
42867                     if (!start && sofar + current >= from) {
42868                         portion = (from - sofar) / current;
42869                         start = [
42870                             a[0] + portion * (b[0] - a[0]),
42871                             a[1] + portion * (b[1] - a[1])
42872                         ];
42873                         i0 = i + 1;
42874                     }
42875                     if (!end && sofar + current >= to) {
42876                         portion = (to - sofar) / current;
42877                         end = [
42878                             a[0] + portion * (b[0] - a[0]),
42879                             a[1] + portion * (b[1] - a[1])
42880                         ];
42881                         i1 = i + 1;
42882                     }
42883                     sofar += current;
42884                 }
42885
42886                 var ret = nodes.slice(i0, i1);
42887                 ret.unshift(start);
42888                 ret.push(end);
42889                 return ret;
42890             }
42891         }
42892
42893
42894         function getAreaLabel(entity, width, height) {
42895             var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
42896                 extent$$1 = entity.extent(graph),
42897                 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
42898
42899             if (isNaN(centroid[0]) || entitywidth < 20) return;
42900
42901             var iconSize = 18,
42902                 iconX = centroid[0] - (iconSize / 2),
42903                 iconY = centroid[1] - (iconSize / 2),
42904                 margin = 2,
42905                 textOffset = iconSize + margin,
42906                 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
42907
42908             var bbox = {
42909                 minX: iconX,
42910                 minY: iconY,
42911                 maxX: iconX + iconSize,
42912                 maxY: iconY + iconSize
42913             };
42914
42915             // try to add icon
42916             if (tryInsert([bbox], entity.id + 'I', true)) {
42917                 if (width && entitywidth >= width + 20) {
42918                     var labelX = centroid[0],
42919                         labelY = centroid[1] + textOffset;
42920
42921                     bbox = {
42922                         minX: labelX - (width / 2) - margin,
42923                         minY: labelY - (height / 2) - margin,
42924                         maxX: labelX + (width / 2) + margin,
42925                         maxY: labelY + (height / 2) + margin
42926                     };
42927
42928                     // try to add label
42929                     if (tryInsert([bbox], entity.id, true)) {
42930                         p.x = labelX;
42931                         p.y = labelY;
42932                         p.textAnchor = 'middle';
42933                         p.height = height;
42934                     }
42935                 }
42936
42937                 return p;
42938             }
42939         }
42940
42941
42942         function tryInsert(bboxes, id, saveSkipped) {
42943             var skipped = false,
42944                 bbox;
42945
42946             for (var i = 0; i < bboxes.length; i++) {
42947                 bbox = bboxes[i];
42948                 bbox.id = id;
42949
42950                 // Check that label is visible
42951                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
42952                     skipped = true;
42953                     break;
42954                 }
42955                 if (rdrawn.collides(bbox)) {
42956                     skipped = true;
42957                     break;
42958                 }
42959             }
42960
42961             entitybboxes[id] = bboxes;
42962
42963             if (skipped) {
42964                 if (saveSkipped) {
42965                     rskipped.load(bboxes);
42966                 }
42967             } else {
42968                 rdrawn.load(bboxes);
42969             }
42970
42971             return !skipped;
42972         }
42973
42974
42975         var label = selection$$1.selectAll('.layer-label'),
42976             halo = selection$$1.selectAll('.layer-halo');
42977
42978         // points
42979         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
42980         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
42981
42982         // lines
42983         drawLinePaths(halo, labelled.line, filter, '', positions.line);
42984         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
42985         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
42986
42987         // areas
42988         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
42989         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
42990         drawAreaIcons(label, labelled.area, filter, 'arealabel-icon', positions.area);
42991
42992         // debug
42993         drawCollisionBoxes(label, rskipped, 'debug-skipped');
42994         drawCollisionBoxes(label, rdrawn, 'debug-drawn');
42995
42996         selection$$1.call(filterLabels);
42997     }
42998
42999
43000     function filterLabels(selection$$1) {
43001         var layers = selection$$1
43002             .selectAll('.layer-label, .layer-halo');
43003
43004         layers.selectAll('.proximate')
43005             .classed('proximate', false);
43006
43007         var mouse$$1 = context.mouse(),
43008             graph = context.graph(),
43009             selectedIDs = context.selectedIDs(),
43010             ids = [],
43011             pad, bbox;
43012
43013         // hide labels near the mouse
43014         if (mouse$$1) {
43015             pad = 20;
43016             bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad };
43017             ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43018         }
43019
43020         // hide labels along selected ways, or near selected vertices
43021         for (var i = 0; i < selectedIDs.length; i++) {
43022             var entity = graph.hasEntity(selectedIDs[i]);
43023             if (!entity) continue;
43024             var geometry = entity.geometry(graph);
43025
43026             if (geometry === 'line') {
43027                 ids.push(selectedIDs[i]);
43028             } else if (geometry === 'vertex') {
43029                 var point = context.projection(entity.loc);
43030                 pad = 10;
43031                 bbox = { minX: point[0] - pad, minY: point[1] - pad, maxX: point[0] + pad, maxY: point[1] + pad };
43032                 ids.push.apply(ids, lodash.map(rdrawn.search(bbox), 'id'));
43033             }
43034         }
43035
43036         layers.selectAll(utilEntitySelector(ids))
43037             .classed('proximate', true);
43038     }
43039
43040
43041     var throttleFilterLabels = lodash.throttle(filterLabels, 100);
43042
43043
43044     drawLabels.observe = function(selection$$1) {
43045         var listener = function() { throttleFilterLabels(selection$$1); };
43046         selection$$1.on('mousemove.hidelabels', listener);
43047         context.on('enter.hidelabels', listener);
43048     };
43049
43050
43051     drawLabels.off = function(selection$$1) {
43052         throttleFilterLabels.cancel();
43053         selection$$1.on('mousemove.hidelabels', null);
43054         context.on('enter.hidelabels', null);
43055     };
43056
43057
43058     return drawLabels;
43059 }
43060
43061 // Copies a variable number of methods from source to target.
43062 function utilRebind(target, source) {
43063     var i = 1, n = arguments.length, method;
43064     while (++i < n) {
43065         target[method = arguments[i]] = d3_rebind(target, source, source[method]);
43066     }
43067     return target;
43068 }
43069
43070 // Method is assumed to be a standard D3 getter-setter:
43071 // If passed with no arguments, gets the value.
43072 // If passed with arguments, sets the value and returns the target.
43073 function d3_rebind(target, source, method) {
43074     return function() {
43075         var value = method.apply(source, arguments);
43076         return value === source ? target : value;
43077     };
43078 }
43079
43080 function refresh(selection, node) {
43081     var cr = node.getBoundingClientRect();
43082     var prop = [cr.width, cr.height];
43083     selection.property('__dimensions__', prop);
43084     return prop;
43085 }
43086
43087 function utilGetDimensions(selection, force) {
43088     if (!selection || selection.empty()) {
43089         return [0, 0];
43090     }
43091     var node = selection.node(),
43092         cached = selection.property('__dimensions__');
43093     return (!cached || force) ? refresh(selection, node) : cached;
43094 }
43095
43096
43097 function utilSetDimensions(selection, dimensions) {
43098     if (!selection || selection.empty()) {
43099         return selection;
43100     }
43101     var node = selection.node();
43102     if (dimensions === null) {
43103         refresh(selection, node);
43104         return selection;
43105     }
43106     return selection
43107         .property('__dimensions__', [dimensions[0], dimensions[1]])
43108         .attr('width', dimensions[0])
43109         .attr('height', dimensions[1]);
43110 }
43111
43112 function svgPointTransform(projection) {
43113     return function(entity) {
43114         // http://jsperf.com/short-array-join
43115         var pt = projection(entity.loc);
43116         return 'translate(' + pt[0] + ',' + pt[1] + ')';
43117     };
43118 }
43119
43120 function d3geoTile() {
43121   var size = [960, 500],
43122       scale = 256,
43123       scaleExtent = [0, 20],
43124       translate = [size[0] / 2, size[1] / 2],
43125       zoomDelta = 0;
43126
43127   function bound(_) {
43128       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43129   }
43130
43131   function tile() {
43132     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43133         z0 = bound(Math.round(z + zoomDelta)),
43134         k = Math.pow(2, z - z0 + 8),
43135         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43136         tiles = [],
43137         cols = range(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43138         rows = range(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43139
43140     rows.forEach(function(y) {
43141       cols.forEach(function(x) {
43142         tiles.push([x, y, z0]);
43143       });
43144     });
43145
43146     tiles.translate = origin;
43147     tiles.scale = k;
43148
43149     return tiles;
43150   }
43151
43152   tile.scaleExtent = function(_) {
43153     if (!arguments.length) return scaleExtent;
43154     scaleExtent = _;
43155     return tile;
43156   };
43157
43158   tile.size = function(_) {
43159     if (!arguments.length) return size;
43160     size = _;
43161     return tile;
43162   };
43163
43164   tile.scale = function(_) {
43165     if (!arguments.length) return scale;
43166     scale = _;
43167     return tile;
43168   };
43169
43170   tile.translate = function(_) {
43171     if (!arguments.length) return translate;
43172     translate = _;
43173     return tile;
43174   };
43175
43176   tile.zoomDelta = function(_) {
43177     if (!arguments.length) return zoomDelta;
43178     zoomDelta = +_;
43179     return tile;
43180   };
43181
43182   return tile;
43183 }
43184
43185 /* global Mapillary:false */
43186 var apibase = 'https://a.mapillary.com/v2/';
43187 var viewercss = 'mapillary-js/mapillary.min.css';
43188 var viewerjs = 'mapillary-js/mapillary.min.js';
43189 var trafficocss = 'traffico/stylesheets/traffico.css';
43190 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43191 var maxResults = 1000;
43192 var tileZoom = 14;
43193 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43194 var mapillaryCache;
43195 var mapillaryClicks;
43196 var mapillaryImage;
43197 var mapillarySignDefs;
43198 var mapillaryViewer;
43199
43200
43201 function abortRequest(i) {
43202     i.abort();
43203 }
43204
43205
43206 function nearNullIsland(x, y, z) {
43207     if (z >= 7) {
43208         var center = Math.pow(2, z - 1),
43209             width = Math.pow(2, z - 6),
43210             min$$1 = center - (width / 2),
43211             max$$1 = center + (width / 2) - 1;
43212         return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43213     }
43214     return false;
43215 }
43216
43217
43218 function maxPageAtZoom(z) {
43219     if (z < 15)   return 2;
43220     if (z === 15) return 5;
43221     if (z === 16) return 10;
43222     if (z === 17) return 20;
43223     if (z === 18) return 40;
43224     if (z > 18)   return 80;
43225 }
43226
43227
43228 function getTiles(projection) {
43229     var s = projection.scale() * 2 * Math.PI,
43230         z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43231         ts = 256 * Math.pow(2, z - tileZoom),
43232         origin = [
43233             s / 2 - projection.translate()[0],
43234             s / 2 - projection.translate()[1]];
43235
43236     return d3geoTile()
43237         .scaleExtent([tileZoom, tileZoom])
43238         .scale(s)
43239         .size(projection.clipExtent()[1])
43240         .translate(projection.translate())()
43241         .map(function(tile) {
43242             var x = tile[0] * ts - origin[0],
43243                 y = tile[1] * ts - origin[1];
43244
43245             return {
43246                 id: tile.toString(),
43247                 xyz: tile,
43248                 extent: geoExtent$$1(
43249                     projection.invert([x, y + ts]),
43250                     projection.invert([x + ts, y])
43251                 )
43252             };
43253         });
43254 }
43255
43256
43257 function loadTiles(which, url, projection) {
43258     var s = projection.scale() * 2 * Math.PI,
43259         currZoom = Math.floor(Math.max(Math.log(s) / Math.log(2) - 8, 0));
43260
43261     var tiles = getTiles(projection).filter(function(t) {
43262             return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
43263         });
43264
43265     lodash.filter(which.inflight, function(v, k) {
43266         var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
43267         if (!wanted) delete which.inflight[k];
43268         return !wanted;
43269     }).map(abortRequest);
43270
43271     tiles.forEach(function(tile) {
43272         loadNextTilePage(which, currZoom, url, tile);
43273     });
43274 }
43275
43276
43277 function loadNextTilePage(which, currZoom, url, tile) {
43278     var cache = mapillaryCache[which],
43279         rect = tile.extent.rectangle(),
43280         maxPages = maxPageAtZoom(currZoom),
43281         nextPage = cache.nextPage[tile.id] || 0;
43282
43283     if (nextPage > maxPages) return;
43284
43285     var id = tile.id + ',' + String(nextPage);
43286     if (cache.loaded[id] || cache.inflight[id]) return;
43287
43288     cache.inflight[id] = json(url +
43289         utilQsString({
43290             geojson: 'true',
43291             limit: maxResults,
43292             page: nextPage,
43293             client_id: clientId,
43294             min_lon: rect[0],
43295             min_lat: rect[1],
43296             max_lon: rect[2],
43297             max_lat: rect[3]
43298         }), function(err, data) {
43299             cache.loaded[id] = true;
43300             delete cache.inflight[id];
43301             if (err || !data.features || !data.features.length) return;
43302
43303             var features = [],
43304                 feature, loc, d;
43305
43306             for (var i = 0; i < data.features.length; i++) {
43307                 feature = data.features[i];
43308                 loc = feature.geometry.coordinates;
43309                 d = { key: feature.properties.key, loc: loc };
43310                 if (which === 'images') d.ca = feature.properties.ca;
43311                 if (which === 'signs') d.signs = feature.properties.rects;
43312
43313                 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
43314             }
43315
43316             cache.rtree.load(features);
43317
43318             if (which === 'images') dispatch$2.call('loadedImages');
43319             if (which === 'signs') dispatch$2.call('loadedSigns');
43320
43321             if (data.features.length === maxResults) {  // more pages to load
43322                 cache.nextPage[tile.id] = nextPage + 1;
43323                 loadNextTilePage(which, currZoom, url, tile);
43324             } else {
43325                 cache.nextPage[tile.id] = Infinity;     // no more pages to load
43326             }
43327         }
43328     );
43329 }
43330
43331
43332 // partition viewport into `psize` x `psize` regions
43333 function partitionViewport(psize, projection) {
43334     var dimensions = projection.clipExtent()[1];
43335     psize = psize || 16;
43336     var cols = range(0, dimensions[0], psize),
43337         rows = range(0, dimensions[1], psize),
43338         partitions = [];
43339
43340     rows.forEach(function(y) {
43341         cols.forEach(function(x) {
43342             var min$$1 = [x, y + psize],
43343                 max$$1 = [x + psize, y];
43344             partitions.push(
43345                 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
43346         });
43347     });
43348
43349     return partitions;
43350 }
43351
43352
43353 // no more than `limit` results per partition.
43354 function searchLimited(psize, limit, projection, rtree) {
43355     limit = limit || 3;
43356
43357     var partitions = partitionViewport(psize, projection);
43358     return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
43359         return rtree.search(extent$$1.bbox())
43360             .slice(0, limit)
43361             .map(function(d) { return d.data; });
43362     })));
43363 }
43364
43365
43366
43367 var serviceMapillary = {
43368
43369     init: function() {
43370         if (!mapillaryCache) {
43371             this.reset();
43372         }
43373
43374         this.event = utilRebind(this, dispatch$2, 'on');
43375     },
43376
43377     reset: function() {
43378         var cache = mapillaryCache;
43379
43380         if (cache) {
43381             if (cache.images && cache.images.inflight) {
43382                 lodash.forEach(cache.images.inflight, abortRequest);
43383             }
43384             if (cache.signs && cache.signs.inflight) {
43385                 lodash.forEach(cache.signs.inflight, abortRequest);
43386             }
43387         }
43388
43389         mapillaryCache = {
43390             images: { inflight: {}, loaded: {}, nextPage: {}, rtree: index$8() },
43391             signs:  { inflight: {}, loaded: {}, nextPage: {}, rtree: index$8() }
43392         };
43393
43394         mapillaryImage = null;
43395         mapillaryClicks = [];
43396     },
43397
43398
43399     images: function(projection) {
43400         var psize = 16, limit = 3;
43401         return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
43402     },
43403
43404
43405     signs: function(projection) {
43406         var psize = 32, limit = 3;
43407         return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
43408     },
43409
43410
43411     signsSupported: function() {
43412         var detected = utilDetect();
43413         if (detected.ie) return false;
43414         if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
43415         return true;
43416     },
43417
43418
43419     signHTML: function(d) {
43420         if (!mapillarySignDefs) return;
43421
43422         var detectionPackage = d.signs[0].package,
43423             type = d.signs[0].type,
43424             country = detectionPackage.split('_')[1];
43425
43426         return mapillarySignDefs[country][type];
43427     },
43428
43429
43430     loadImages: function(projection) {
43431         var url = apibase + 'search/im/geojson?';
43432         loadTiles('images', url, projection);
43433     },
43434
43435
43436     loadSigns: function(context, projection) {
43437         var url = apibase + 'search/im/geojson/or?';
43438         loadTiles('signs', url, projection);
43439
43440         // load traffico css
43441         select('head').selectAll('#traffico')
43442             .data([0])
43443             .enter()
43444             .append('link')
43445             .attr('id', 'traffico')
43446             .attr('rel', 'stylesheet')
43447             .attr('href', context.asset(trafficocss));
43448
43449         // load traffico sign defs
43450         if (!mapillarySignDefs) {
43451             mapillarySignDefs = {};
43452             lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
43453                 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
43454                     if (err) return;
43455                     if (region === 'de') region = 'eu';
43456                     mapillarySignDefs[region] = data;
43457                 });
43458             });
43459         }
43460     },
43461
43462
43463     loadViewer: function(context) {
43464         var that = this;
43465         var wrap = select('#content').selectAll('.mapillary-wrap')
43466             .data([0]);
43467
43468         var enter = wrap.enter()
43469             .append('div')
43470             .attr('class', 'mapillary-wrap')
43471             .classed('al', true)       // 'al'=left,  'ar'=right
43472             .classed('hidden', true);
43473
43474         enter
43475             .append('button')
43476             .attr('class', 'thumb-hide')
43477             .on('click', function () { that.hideViewer(); })
43478             .append('div')
43479             .call(svgIcon('#icon-close'));
43480
43481         enter
43482             .append('div')
43483             .attr('id', 'mly')
43484             .attr('class', 'mly-wrapper')
43485             .classed('active', false);
43486
43487         // load mapillary-viewercss
43488         select('head').selectAll('#mapillary-viewercss')
43489             .data([0])
43490             .enter()
43491             .append('link')
43492             .attr('id', 'mapillary-viewercss')
43493             .attr('rel', 'stylesheet')
43494             .attr('href', context.asset(viewercss));
43495
43496         // load mapillary-viewerjs
43497         select('head').selectAll('#mapillary-viewerjs')
43498             .data([0])
43499             .enter()
43500             .append('script')
43501             .attr('id', 'mapillary-viewerjs')
43502             .attr('src', context.asset(viewerjs));
43503     },
43504
43505
43506     showViewer: function() {
43507         select('#content')
43508             .selectAll('.mapillary-wrap')
43509             .classed('hidden', false)
43510             .selectAll('.mly-wrapper')
43511             .classed('active', true);
43512
43513         return this;
43514     },
43515
43516
43517     hideViewer: function() {
43518         select('#content')
43519             .selectAll('.mapillary-wrap')
43520             .classed('hidden', true)
43521             .selectAll('.mly-wrapper')
43522             .classed('active', false);
43523
43524         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
43525             .classed('selected', false);
43526
43527         mapillaryImage = null;
43528         return this;
43529     },
43530
43531
43532     updateViewer: function(imageKey, context) {
43533         if (!imageKey) return;
43534
43535         if (!mapillaryViewer) {
43536             this.initViewer(imageKey, context);
43537         } else {
43538             mapillaryViewer.moveToKey(imageKey);
43539         }
43540
43541         return this;
43542     },
43543
43544
43545     initViewer: function(imageKey, context) {
43546         var that = this;
43547         if (Mapillary && imageKey) {
43548             var opts = {
43549                 baseImageSize: 320,
43550                 component: {
43551                     cover: false,
43552                     keyboard: false
43553                 }
43554             };
43555
43556             mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
43557             mapillaryViewer.on('nodechanged', nodeChanged);
43558         }
43559
43560         function nodeChanged(node) {
43561             var clicks = mapillaryClicks;
43562             var index = clicks.indexOf(node.key);
43563             if (index > -1) {    // nodechange initiated from clicking on a marker..
43564                 clicks.splice(index, 1);
43565             } else {             // nodechange initiated from the Mapillary viewer controls..
43566                 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
43567                 context.map().centerEase(loc);
43568                 that.selectedImage(node.key, false);
43569             }
43570         }
43571     },
43572
43573
43574     selectedImage: function(imageKey, fromClick) {
43575         if (!arguments.length) return mapillaryImage;
43576
43577         mapillaryImage = imageKey;
43578         if (fromClick) {
43579             mapillaryClicks.push(imageKey);
43580         }
43581
43582         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
43583             .classed('selected', function(d) { return d.key === imageKey; });
43584
43585         return this;
43586     },
43587
43588
43589     cache: function(_) {
43590         if (!arguments.length) return mapillaryCache;
43591         mapillaryCache = _;
43592         return this;
43593     },
43594
43595
43596     signDefs: function(_) {
43597         if (!arguments.length) return mapillarySignDefs;
43598         mapillarySignDefs = _;
43599         return this;
43600     }
43601
43602 };
43603
43604 var endpoint = 'https://nominatim.openstreetmap.org/reverse?';
43605 var nominatimCache;
43606
43607
43608 var serviceNominatim = {
43609
43610     init: function() { nominatimCache = index$8(); },
43611     reset: function() { nominatimCache = index$8(); },
43612
43613
43614     countryCode: function (location, callback) {
43615         var countryCodes = nominatimCache.search(
43616             { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
43617         );
43618
43619         if (countryCodes.length > 0) {
43620             return callback(null, countryCodes[0].data);
43621         }
43622
43623         json(endpoint +
43624             utilQsString({
43625                 format: 'json',
43626                 addressdetails: 1,
43627                 lat: location[1],
43628                 lon: location[0]
43629             }), function(err, result) {
43630                 if (err)
43631                     return callback(err);
43632                 else if (result && result.error)
43633                     return callback(result.error);
43634
43635                 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
43636                 nominatimCache.insert(Object.assign(extent$$1.bbox(),
43637                     { data: result.address.country_code }
43638                 ));
43639
43640                 callback(null, result.address.country_code);
43641             }
43642         );
43643     }
43644
43645 };
43646
43647 var hashes$1 = createCommonjsModule(function (module, exports) {
43648 /**
43649  * jshashes - https://github.com/h2non/jshashes
43650  * Released under the "New BSD" license
43651  *
43652  * Algorithms specification:
43653  *
43654  * MD5 - http://www.ietf.org/rfc/rfc1321.txt
43655  * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
43656  * SHA1   - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43657  * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43658  * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43659  * HMAC - http://www.ietf.org/rfc/rfc2104.txt
43660  */
43661 (function() {
43662   var Hashes;
43663
43664   function utf8Encode(str) {
43665     var x, y, output = '',
43666       i = -1,
43667       l;
43668
43669     if (str && str.length) {
43670       l = str.length;
43671       while ((i += 1) < l) {
43672         /* Decode utf-16 surrogate pairs */
43673         x = str.charCodeAt(i);
43674         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
43675         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
43676           x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
43677           i += 1;
43678         }
43679         /* Encode output as utf-8 */
43680         if (x <= 0x7F) {
43681           output += String.fromCharCode(x);
43682         } else if (x <= 0x7FF) {
43683           output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
43684             0x80 | (x & 0x3F));
43685         } else if (x <= 0xFFFF) {
43686           output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
43687             0x80 | ((x >>> 6) & 0x3F),
43688             0x80 | (x & 0x3F));
43689         } else if (x <= 0x1FFFFF) {
43690           output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
43691             0x80 | ((x >>> 12) & 0x3F),
43692             0x80 | ((x >>> 6) & 0x3F),
43693             0x80 | (x & 0x3F));
43694         }
43695       }
43696     }
43697     return output;
43698   }
43699
43700   function utf8Decode(str) {
43701     var i, ac, c1, c2, c3, arr = [],
43702       l;
43703     i = ac = c1 = c2 = c3 = 0;
43704
43705     if (str && str.length) {
43706       l = str.length;
43707       str += '';
43708
43709       while (i < l) {
43710         c1 = str.charCodeAt(i);
43711         ac += 1;
43712         if (c1 < 128) {
43713           arr[ac] = String.fromCharCode(c1);
43714           i += 1;
43715         } else if (c1 > 191 && c1 < 224) {
43716           c2 = str.charCodeAt(i + 1);
43717           arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
43718           i += 2;
43719         } else {
43720           c2 = str.charCodeAt(i + 1);
43721           c3 = str.charCodeAt(i + 2);
43722           arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
43723           i += 3;
43724         }
43725       }
43726     }
43727     return arr.join('');
43728   }
43729
43730   /**
43731    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
43732    * to work around bugs in some JS interpreters.
43733    */
43734
43735   function safe_add(x, y) {
43736     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
43737       msw = (x >> 16) + (y >> 16) + (lsw >> 16);
43738     return (msw << 16) | (lsw & 0xFFFF);
43739   }
43740
43741   /**
43742    * Bitwise rotate a 32-bit number to the left.
43743    */
43744
43745   function bit_rol(num, cnt) {
43746     return (num << cnt) | (num >>> (32 - cnt));
43747   }
43748
43749   /**
43750    * Convert a raw string to a hex string
43751    */
43752
43753   function rstr2hex(input, hexcase) {
43754     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
43755       output = '',
43756       x, i = 0,
43757       l = input.length;
43758     for (; i < l; i += 1) {
43759       x = input.charCodeAt(i);
43760       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
43761     }
43762     return output;
43763   }
43764
43765   /**
43766    * Encode a string as utf-16
43767    */
43768
43769   function str2rstr_utf16le(input) {
43770     var i, l = input.length,
43771       output = '';
43772     for (i = 0; i < l; i += 1) {
43773       output += String.fromCharCode(input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF);
43774     }
43775     return output;
43776   }
43777
43778   function str2rstr_utf16be(input) {
43779     var i, l = input.length,
43780       output = '';
43781     for (i = 0; i < l; i += 1) {
43782       output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF);
43783     }
43784     return output;
43785   }
43786
43787   /**
43788    * Convert an array of big-endian words to a string
43789    */
43790
43791   function binb2rstr(input) {
43792     var i, l = input.length * 32,
43793       output = '';
43794     for (i = 0; i < l; i += 8) {
43795       output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
43796     }
43797     return output;
43798   }
43799
43800   /**
43801    * Convert an array of little-endian words to a string
43802    */
43803
43804   function binl2rstr(input) {
43805     var i, l = input.length * 32,
43806       output = '';
43807     for (i = 0; i < l; i += 8) {
43808       output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
43809     }
43810     return output;
43811   }
43812
43813   /**
43814    * Convert a raw string to an array of little-endian words
43815    * Characters >255 have their high-byte silently ignored.
43816    */
43817
43818   function rstr2binl(input) {
43819     var i, l = input.length * 8,
43820       output = Array(input.length >> 2),
43821       lo = output.length;
43822     for (i = 0; i < lo; i += 1) {
43823       output[i] = 0;
43824     }
43825     for (i = 0; i < l; i += 8) {
43826       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
43827     }
43828     return output;
43829   }
43830
43831   /**
43832    * Convert a raw string to an array of big-endian words
43833    * Characters >255 have their high-byte silently ignored.
43834    */
43835
43836   function rstr2binb(input) {
43837     var i, l = input.length * 8,
43838       output = Array(input.length >> 2),
43839       lo = output.length;
43840     for (i = 0; i < lo; i += 1) {
43841       output[i] = 0;
43842     }
43843     for (i = 0; i < l; i += 8) {
43844       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
43845     }
43846     return output;
43847   }
43848
43849   /**
43850    * Convert a raw string to an arbitrary string encoding
43851    */
43852
43853   function rstr2any(input, encoding) {
43854     var divisor = encoding.length,
43855       remainders = Array(),
43856       i, q, x, ld, quotient, dividend, output, full_length;
43857
43858     /* Convert to an array of 16-bit big-endian values, forming the dividend */
43859     dividend = Array(Math.ceil(input.length / 2));
43860     ld = dividend.length;
43861     for (i = 0; i < ld; i += 1) {
43862       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
43863     }
43864
43865     /**
43866      * Repeatedly perform a long division. The binary array forms the dividend,
43867      * the length of the encoding is the divisor. Once computed, the quotient
43868      * forms the dividend for the next step. We stop when the dividend is zerHashes.
43869      * All remainders are stored for later use.
43870      */
43871     while (dividend.length > 0) {
43872       quotient = Array();
43873       x = 0;
43874       for (i = 0; i < dividend.length; i += 1) {
43875         x = (x << 16) + dividend[i];
43876         q = Math.floor(x / divisor);
43877         x -= q * divisor;
43878         if (quotient.length > 0 || q > 0) {
43879           quotient[quotient.length] = q;
43880         }
43881       }
43882       remainders[remainders.length] = x;
43883       dividend = quotient;
43884     }
43885
43886     /* Convert the remainders to the output string */
43887     output = '';
43888     for (i = remainders.length - 1; i >= 0; i--) {
43889       output += encoding.charAt(remainders[i]);
43890     }
43891
43892     /* Append leading zero equivalents */
43893     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
43894     for (i = output.length; i < full_length; i += 1) {
43895       output = encoding[0] + output;
43896     }
43897     return output;
43898   }
43899
43900   /**
43901    * Convert a raw string to a base-64 string
43902    */
43903
43904   function rstr2b64(input, b64pad) {
43905     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
43906       output = '',
43907       len = input.length,
43908       i, j, triplet;
43909     b64pad = b64pad || '=';
43910     for (i = 0; i < len; i += 3) {
43911       triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
43912       for (j = 0; j < 4; j += 1) {
43913         if (i * 8 + j * 6 > input.length * 8) {
43914           output += b64pad;
43915         } else {
43916           output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
43917         }
43918       }
43919     }
43920     return output;
43921   }
43922
43923   Hashes = {
43924     /**
43925      * @property {String} version
43926      * @readonly
43927      */
43928     VERSION: '1.0.5',
43929     /**
43930      * @member Hashes
43931      * @class Base64
43932      * @constructor
43933      */
43934     Base64: function() {
43935       // private properties
43936       var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
43937         pad = '=', // default pad according with the RFC standard
43938         url = false, // URL encoding support @todo
43939         utf8 = true; // by default enable UTF-8 support encoding
43940
43941       // public method for encoding
43942       this.encode = function(input) {
43943         var i, j, triplet,
43944           output = '',
43945           len = input.length;
43946
43947         pad = pad || '=';
43948         input = (utf8) ? utf8Encode(input) : input;
43949
43950         for (i = 0; i < len; i += 3) {
43951           triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
43952           for (j = 0; j < 4; j += 1) {
43953             if (i * 8 + j * 6 > len * 8) {
43954               output += pad;
43955             } else {
43956               output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
43957             }
43958           }
43959         }
43960         return output;
43961       };
43962
43963       // public method for decoding
43964       this.decode = function(input) {
43965         // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
43966         var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
43967           dec = '',
43968           arr = [];
43969         if (!input) {
43970           return input;
43971         }
43972
43973         i = ac = 0;
43974         input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
43975         //input += '';
43976
43977         do { // unpack four hexets into three octets using index points in b64
43978           h1 = tab.indexOf(input.charAt(i += 1));
43979           h2 = tab.indexOf(input.charAt(i += 1));
43980           h3 = tab.indexOf(input.charAt(i += 1));
43981           h4 = tab.indexOf(input.charAt(i += 1));
43982
43983           bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
43984
43985           o1 = bits >> 16 & 0xff;
43986           o2 = bits >> 8 & 0xff;
43987           o3 = bits & 0xff;
43988           ac += 1;
43989
43990           if (h3 === 64) {
43991             arr[ac] = String.fromCharCode(o1);
43992           } else if (h4 === 64) {
43993             arr[ac] = String.fromCharCode(o1, o2);
43994           } else {
43995             arr[ac] = String.fromCharCode(o1, o2, o3);
43996           }
43997         } while (i < input.length);
43998
43999         dec = arr.join('');
44000         dec = (utf8) ? utf8Decode(dec) : dec;
44001
44002         return dec;
44003       };
44004
44005       // set custom pad string
44006       this.setPad = function(str) {
44007         pad = str || pad;
44008         return this;
44009       };
44010       // set custom tab string characters
44011       this.setTab = function(str) {
44012         tab = str || tab;
44013         return this;
44014       };
44015       this.setUTF8 = function(bool) {
44016         if (typeof bool === 'boolean') {
44017           utf8 = bool;
44018         }
44019         return this;
44020       };
44021     },
44022
44023     /**
44024      * CRC-32 calculation
44025      * @member Hashes
44026      * @method CRC32
44027      * @static
44028      * @param {String} str Input String
44029      * @return {String}
44030      */
44031     CRC32: function(str) {
44032       var crc = 0,
44033         x = 0,
44034         y = 0,
44035         table, i, iTop;
44036       str = utf8Encode(str);
44037
44038       table = [
44039         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
44040         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
44041         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
44042         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
44043         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
44044         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
44045         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
44046         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
44047         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
44048         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
44049         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
44050         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
44051         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
44052         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
44053         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
44054         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
44055         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
44056         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
44057         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
44058         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
44059         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
44060         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
44061         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44062         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44063         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44064         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44065       ].join('');
44066
44067       crc = crc ^ (-1);
44068       for (i = 0, iTop = str.length; i < iTop; i += 1) {
44069         y = (crc ^ str.charCodeAt(i)) & 0xFF;
44070         x = '0x' + table.substr(y * 9, 8);
44071         crc = (crc >>> 8) ^ x;
44072       }
44073       // always return a positive number (that's what >>> 0 does)
44074       return (crc ^ (-1)) >>> 0;
44075     },
44076     /**
44077      * @member Hashes
44078      * @class MD5
44079      * @constructor
44080      * @param {Object} [config]
44081      *
44082      * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44083      * Digest Algorithm, as defined in RFC 1321.
44084      * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44085      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44086      * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44087      */
44088     MD5: function(options) {
44089       /**
44090        * Private config properties. You may need to tweak these to be compatible with
44091        * the server-side, but the defaults work in most cases.
44092        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44093        */
44094       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44095         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44096         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44097
44098       // privileged (public) methods
44099       this.hex = function(s) {
44100         return rstr2hex(rstr(s, utf8), hexcase);
44101       };
44102       this.b64 = function(s) {
44103         return rstr2b64(rstr(s), b64pad);
44104       };
44105       this.any = function(s, e) {
44106         return rstr2any(rstr(s, utf8), e);
44107       };
44108       this.raw = function(s) {
44109         return rstr(s, utf8);
44110       };
44111       this.hex_hmac = function(k, d) {
44112         return rstr2hex(rstr_hmac(k, d), hexcase);
44113       };
44114       this.b64_hmac = function(k, d) {
44115         return rstr2b64(rstr_hmac(k, d), b64pad);
44116       };
44117       this.any_hmac = function(k, d, e) {
44118         return rstr2any(rstr_hmac(k, d), e);
44119       };
44120       /**
44121        * Perform a simple self-test to see if the VM is working
44122        * @return {String} Hexadecimal hash sample
44123        */
44124       this.vm_test = function() {
44125         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44126       };
44127       /**
44128        * Enable/disable uppercase hexadecimal returned string
44129        * @param {Boolean}
44130        * @return {Object} this
44131        */
44132       this.setUpperCase = function(a) {
44133         if (typeof a === 'boolean') {
44134           hexcase = a;
44135         }
44136         return this;
44137       };
44138       /**
44139        * Defines a base64 pad string
44140        * @param {String} Pad
44141        * @return {Object} this
44142        */
44143       this.setPad = function(a) {
44144         b64pad = a || b64pad;
44145         return this;
44146       };
44147       /**
44148        * Defines a base64 pad string
44149        * @param {Boolean}
44150        * @return {Object} [this]
44151        */
44152       this.setUTF8 = function(a) {
44153         if (typeof a === 'boolean') {
44154           utf8 = a;
44155         }
44156         return this;
44157       };
44158
44159       // private methods
44160
44161       /**
44162        * Calculate the MD5 of a raw string
44163        */
44164
44165       function rstr(s) {
44166         s = (utf8) ? utf8Encode(s) : s;
44167         return binl2rstr(binl(rstr2binl(s), s.length * 8));
44168       }
44169
44170       /**
44171        * Calculate the HMAC-MD5, of a key and some data (raw strings)
44172        */
44173
44174       function rstr_hmac(key, data) {
44175         var bkey, ipad, opad, hash, i;
44176
44177         key = (utf8) ? utf8Encode(key) : key;
44178         data = (utf8) ? utf8Encode(data) : data;
44179         bkey = rstr2binl(key);
44180         if (bkey.length > 16) {
44181           bkey = binl(bkey, key.length * 8);
44182         }
44183
44184         ipad = Array(16), opad = Array(16);
44185         for (i = 0; i < 16; i += 1) {
44186           ipad[i] = bkey[i] ^ 0x36363636;
44187           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44188         }
44189         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44190         return binl2rstr(binl(opad.concat(hash), 512 + 128));
44191       }
44192
44193       /**
44194        * Calculate the MD5 of an array of little-endian words, and a bit length.
44195        */
44196
44197       function binl(x, len) {
44198         var i, olda, oldb, oldc, oldd,
44199           a = 1732584193,
44200           b = -271733879,
44201           c = -1732584194,
44202           d = 271733878;
44203
44204         /* append padding */
44205         x[len >> 5] |= 0x80 << ((len) % 32);
44206         x[(((len + 64) >>> 9) << 4) + 14] = len;
44207
44208         for (i = 0; i < x.length; i += 16) {
44209           olda = a;
44210           oldb = b;
44211           oldc = c;
44212           oldd = d;
44213
44214           a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44215           d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44216           c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44217           b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44218           a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44219           d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44220           c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44221           b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44222           a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44223           d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44224           c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44225           b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44226           a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44227           d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44228           c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44229           b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44230
44231           a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44232           d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44233           c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44234           b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44235           a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44236           d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44237           c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44238           b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44239           a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44240           d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44241           c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44242           b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44243           a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44244           d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44245           c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44246           b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44247
44248           a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44249           d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44250           c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44251           b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44252           a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44253           d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44254           c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44255           b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44256           a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44257           d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44258           c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44259           b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44260           a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44261           d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44262           c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44263           b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
44264
44265           a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
44266           d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
44267           c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
44268           b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
44269           a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
44270           d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
44271           c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
44272           b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
44273           a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
44274           d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
44275           c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
44276           b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
44277           a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
44278           d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
44279           c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
44280           b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
44281
44282           a = safe_add(a, olda);
44283           b = safe_add(b, oldb);
44284           c = safe_add(c, oldc);
44285           d = safe_add(d, oldd);
44286         }
44287         return Array(a, b, c, d);
44288       }
44289
44290       /**
44291        * These functions implement the four basic operations the algorithm uses.
44292        */
44293
44294       function md5_cmn(q, a, b, x, s, t) {
44295         return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
44296       }
44297
44298       function md5_ff(a, b, c, d, x, s, t) {
44299         return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44300       }
44301
44302       function md5_gg(a, b, c, d, x, s, t) {
44303         return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44304       }
44305
44306       function md5_hh(a, b, c, d, x, s, t) {
44307         return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44308       }
44309
44310       function md5_ii(a, b, c, d, x, s, t) {
44311         return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44312       }
44313     },
44314     /**
44315      * @member Hashes
44316      * @class Hashes.SHA1
44317      * @param {Object} [config]
44318      * @constructor
44319      *
44320      * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
44321      * Version 2.2 Copyright Paul Johnston 2000 - 2009.
44322      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44323      * See http://pajhome.org.uk/crypt/md5 for details.
44324      */
44325     SHA1: function(options) {
44326       /**
44327        * Private config properties. You may need to tweak these to be compatible with
44328        * the server-side, but the defaults work in most cases.
44329        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44330        */
44331       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44332         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44333         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44334
44335       // public methods
44336       this.hex = function(s) {
44337         return rstr2hex(rstr(s, utf8), hexcase);
44338       };
44339       this.b64 = function(s) {
44340         return rstr2b64(rstr(s, utf8), b64pad);
44341       };
44342       this.any = function(s, e) {
44343         return rstr2any(rstr(s, utf8), e);
44344       };
44345       this.raw = function(s) {
44346         return rstr(s, utf8);
44347       };
44348       this.hex_hmac = function(k, d) {
44349         return rstr2hex(rstr_hmac(k, d));
44350       };
44351       this.b64_hmac = function(k, d) {
44352         return rstr2b64(rstr_hmac(k, d), b64pad);
44353       };
44354       this.any_hmac = function(k, d, e) {
44355         return rstr2any(rstr_hmac(k, d), e);
44356       };
44357       /**
44358        * Perform a simple self-test to see if the VM is working
44359        * @return {String} Hexadecimal hash sample
44360        * @public
44361        */
44362       this.vm_test = function() {
44363         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44364       };
44365       /**
44366        * @description Enable/disable uppercase hexadecimal returned string
44367        * @param {boolean}
44368        * @return {Object} this
44369        * @public
44370        */
44371       this.setUpperCase = function(a) {
44372         if (typeof a === 'boolean') {
44373           hexcase = a;
44374         }
44375         return this;
44376       };
44377       /**
44378        * @description Defines a base64 pad string
44379        * @param {string} Pad
44380        * @return {Object} this
44381        * @public
44382        */
44383       this.setPad = function(a) {
44384         b64pad = a || b64pad;
44385         return this;
44386       };
44387       /**
44388        * @description Defines a base64 pad string
44389        * @param {boolean}
44390        * @return {Object} this
44391        * @public
44392        */
44393       this.setUTF8 = function(a) {
44394         if (typeof a === 'boolean') {
44395           utf8 = a;
44396         }
44397         return this;
44398       };
44399
44400       // private methods
44401
44402       /**
44403        * Calculate the SHA-512 of a raw string
44404        */
44405
44406       function rstr(s) {
44407         s = (utf8) ? utf8Encode(s) : s;
44408         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44409       }
44410
44411       /**
44412        * Calculate the HMAC-SHA1 of a key and some data (raw strings)
44413        */
44414
44415       function rstr_hmac(key, data) {
44416         var bkey, ipad, opad, i, hash;
44417         key = (utf8) ? utf8Encode(key) : key;
44418         data = (utf8) ? utf8Encode(data) : data;
44419         bkey = rstr2binb(key);
44420
44421         if (bkey.length > 16) {
44422           bkey = binb(bkey, key.length * 8);
44423         }
44424         ipad = Array(16), opad = Array(16);
44425         for (i = 0; i < 16; i += 1) {
44426           ipad[i] = bkey[i] ^ 0x36363636;
44427           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44428         }
44429         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44430         return binb2rstr(binb(opad.concat(hash), 512 + 160));
44431       }
44432
44433       /**
44434        * Calculate the SHA-1 of an array of big-endian words, and a bit length
44435        */
44436
44437       function binb(x, len) {
44438         var i, j, t, olda, oldb, oldc, oldd, olde,
44439           w = Array(80),
44440           a = 1732584193,
44441           b = -271733879,
44442           c = -1732584194,
44443           d = 271733878,
44444           e = -1009589776;
44445
44446         /* append padding */
44447         x[len >> 5] |= 0x80 << (24 - len % 32);
44448         x[((len + 64 >> 9) << 4) + 15] = len;
44449
44450         for (i = 0; i < x.length; i += 16) {
44451           olda = a,
44452           oldb = b;
44453           oldc = c;
44454           oldd = d;
44455           olde = e;
44456
44457           for (j = 0; j < 80; j += 1) {
44458             if (j < 16) {
44459               w[j] = x[i + j];
44460             } else {
44461               w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
44462             }
44463             t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
44464               safe_add(safe_add(e, w[j]), sha1_kt(j)));
44465             e = d;
44466             d = c;
44467             c = bit_rol(b, 30);
44468             b = a;
44469             a = t;
44470           }
44471
44472           a = safe_add(a, olda);
44473           b = safe_add(b, oldb);
44474           c = safe_add(c, oldc);
44475           d = safe_add(d, oldd);
44476           e = safe_add(e, olde);
44477         }
44478         return Array(a, b, c, d, e);
44479       }
44480
44481       /**
44482        * Perform the appropriate triplet combination function for the current
44483        * iteration
44484        */
44485
44486       function sha1_ft(t, b, c, d) {
44487         if (t < 20) {
44488           return (b & c) | ((~b) & d);
44489         }
44490         if (t < 40) {
44491           return b ^ c ^ d;
44492         }
44493         if (t < 60) {
44494           return (b & c) | (b & d) | (c & d);
44495         }
44496         return b ^ c ^ d;
44497       }
44498
44499       /**
44500        * Determine the appropriate additive constant for the current iteration
44501        */
44502
44503       function sha1_kt(t) {
44504         return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
44505           (t < 60) ? -1894007588 : -899497514;
44506       }
44507     },
44508     /**
44509      * @class Hashes.SHA256
44510      * @param {config}
44511      *
44512      * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
44513      * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
44514      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44515      * See http://pajhome.org.uk/crypt/md5 for details.
44516      * Also http://anmar.eu.org/projects/jssha2/
44517      */
44518     SHA256: function(options) {
44519       /**
44520        * Private properties configuration variables. You may need to tweak these to be compatible with
44521        * the server-side, but the defaults work in most cases.
44522        * @see this.setUpperCase() method
44523        * @see this.setPad() method
44524        */
44525       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
44526         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
44527         /* base-64 pad character. Default '=' for strict RFC compliance   */
44528         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
44529         /* enable/disable utf8 encoding */
44530         sha256_K;
44531
44532       /* privileged (public) methods */
44533       this.hex = function(s) {
44534         return rstr2hex(rstr(s, utf8));
44535       };
44536       this.b64 = function(s) {
44537         return rstr2b64(rstr(s, utf8), b64pad);
44538       };
44539       this.any = function(s, e) {
44540         return rstr2any(rstr(s, utf8), e);
44541       };
44542       this.raw = function(s) {
44543         return rstr(s, utf8);
44544       };
44545       this.hex_hmac = function(k, d) {
44546         return rstr2hex(rstr_hmac(k, d));
44547       };
44548       this.b64_hmac = function(k, d) {
44549         return rstr2b64(rstr_hmac(k, d), b64pad);
44550       };
44551       this.any_hmac = function(k, d, e) {
44552         return rstr2any(rstr_hmac(k, d), e);
44553       };
44554       /**
44555        * Perform a simple self-test to see if the VM is working
44556        * @return {String} Hexadecimal hash sample
44557        * @public
44558        */
44559       this.vm_test = function() {
44560         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44561       };
44562       /**
44563        * Enable/disable uppercase hexadecimal returned string
44564        * @param {boolean}
44565        * @return {Object} this
44566        * @public
44567        */
44568       this.setUpperCase = function(a) {
44569         if (typeof a === 'boolean') {
44570           hexcase = a;
44571         }
44572         return this;
44573       };
44574       /**
44575        * @description Defines a base64 pad string
44576        * @param {string} Pad
44577        * @return {Object} this
44578        * @public
44579        */
44580       this.setPad = function(a) {
44581         b64pad = a || b64pad;
44582         return this;
44583       };
44584       /**
44585        * Defines a base64 pad string
44586        * @param {boolean}
44587        * @return {Object} this
44588        * @public
44589        */
44590       this.setUTF8 = function(a) {
44591         if (typeof a === 'boolean') {
44592           utf8 = a;
44593         }
44594         return this;
44595       };
44596
44597       // private methods
44598
44599       /**
44600        * Calculate the SHA-512 of a raw string
44601        */
44602
44603       function rstr(s, utf8) {
44604         s = (utf8) ? utf8Encode(s) : s;
44605         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44606       }
44607
44608       /**
44609        * Calculate the HMAC-sha256 of a key and some data (raw strings)
44610        */
44611
44612       function rstr_hmac(key, data) {
44613         key = (utf8) ? utf8Encode(key) : key;
44614         data = (utf8) ? utf8Encode(data) : data;
44615         var hash, i = 0,
44616           bkey = rstr2binb(key),
44617           ipad = Array(16),
44618           opad = Array(16);
44619
44620         if (bkey.length > 16) {
44621           bkey = binb(bkey, key.length * 8);
44622         }
44623
44624         for (; i < 16; i += 1) {
44625           ipad[i] = bkey[i] ^ 0x36363636;
44626           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44627         }
44628
44629         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44630         return binb2rstr(binb(opad.concat(hash), 512 + 256));
44631       }
44632
44633       /*
44634        * Main sha256 function, with its support functions
44635        */
44636
44637       function sha256_S(X, n) {
44638         return (X >>> n) | (X << (32 - n));
44639       }
44640
44641       function sha256_R(X, n) {
44642         return (X >>> n);
44643       }
44644
44645       function sha256_Ch(x, y, z) {
44646         return ((x & y) ^ ((~x) & z));
44647       }
44648
44649       function sha256_Maj(x, y, z) {
44650         return ((x & y) ^ (x & z) ^ (y & z));
44651       }
44652
44653       function sha256_Sigma0256(x) {
44654         return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
44655       }
44656
44657       function sha256_Sigma1256(x) {
44658         return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
44659       }
44660
44661       function sha256_Gamma0256(x) {
44662         return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
44663       }
44664
44665       function sha256_Gamma1256(x) {
44666         return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
44667       }
44668
44669       function sha256_Sigma0512(x) {
44670         return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));
44671       }
44672
44673       function sha256_Sigma1512(x) {
44674         return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));
44675       }
44676
44677       function sha256_Gamma0512(x) {
44678         return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));
44679       }
44680
44681       function sha256_Gamma1512(x) {
44682         return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));
44683       }
44684
44685       sha256_K = [
44686         1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
44687         1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
44688         264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
44689         113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
44690         1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
44691         430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
44692         1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
44693       ];
44694
44695       function binb(m, l) {
44696         var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
44697           1359893119, -1694144372, 528734635, 1541459225
44698         ];
44699         var W = new Array(64);
44700         var a, b, c, d, e, f, g, h;
44701         var i, j, T1, T2;
44702
44703         /* append padding */
44704         m[l >> 5] |= 0x80 << (24 - l % 32);
44705         m[((l + 64 >> 9) << 4) + 15] = l;
44706
44707         for (i = 0; i < m.length; i += 16) {
44708           a = HASH[0];
44709           b = HASH[1];
44710           c = HASH[2];
44711           d = HASH[3];
44712           e = HASH[4];
44713           f = HASH[5];
44714           g = HASH[6];
44715           h = HASH[7];
44716
44717           for (j = 0; j < 64; j += 1) {
44718             if (j < 16) {
44719               W[j] = m[j + i];
44720             } else {
44721               W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
44722                 sha256_Gamma0256(W[j - 15])), W[j - 16]);
44723             }
44724
44725             T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
44726               sha256_K[j]), W[j]);
44727             T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
44728             h = g;
44729             g = f;
44730             f = e;
44731             e = safe_add(d, T1);
44732             d = c;
44733             c = b;
44734             b = a;
44735             a = safe_add(T1, T2);
44736           }
44737
44738           HASH[0] = safe_add(a, HASH[0]);
44739           HASH[1] = safe_add(b, HASH[1]);
44740           HASH[2] = safe_add(c, HASH[2]);
44741           HASH[3] = safe_add(d, HASH[3]);
44742           HASH[4] = safe_add(e, HASH[4]);
44743           HASH[5] = safe_add(f, HASH[5]);
44744           HASH[6] = safe_add(g, HASH[6]);
44745           HASH[7] = safe_add(h, HASH[7]);
44746         }
44747         return HASH;
44748       }
44749
44750     },
44751
44752     /**
44753      * @class Hashes.SHA512
44754      * @param {config}
44755      *
44756      * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
44757      * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
44758      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44759      * See http://pajhome.org.uk/crypt/md5 for details.
44760      */
44761     SHA512: function(options) {
44762       /**
44763        * Private properties configuration variables. You may need to tweak these to be compatible with
44764        * the server-side, but the defaults work in most cases.
44765        * @see this.setUpperCase() method
44766        * @see this.setPad() method
44767        */
44768       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
44769         /* hexadecimal output case format. false - lowercase; true - uppercase  */
44770         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
44771         /* base-64 pad character. Default '=' for strict RFC compliance   */
44772         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
44773         /* enable/disable utf8 encoding */
44774         sha512_k;
44775
44776       /* privileged (public) methods */
44777       this.hex = function(s) {
44778         return rstr2hex(rstr(s));
44779       };
44780       this.b64 = function(s) {
44781         return rstr2b64(rstr(s), b64pad);
44782       };
44783       this.any = function(s, e) {
44784         return rstr2any(rstr(s), e);
44785       };
44786       this.raw = function(s) {
44787         return rstr(s, utf8);
44788       };
44789       this.hex_hmac = function(k, d) {
44790         return rstr2hex(rstr_hmac(k, d));
44791       };
44792       this.b64_hmac = function(k, d) {
44793         return rstr2b64(rstr_hmac(k, d), b64pad);
44794       };
44795       this.any_hmac = function(k, d, e) {
44796         return rstr2any(rstr_hmac(k, d), e);
44797       };
44798       /**
44799        * Perform a simple self-test to see if the VM is working
44800        * @return {String} Hexadecimal hash sample
44801        * @public
44802        */
44803       this.vm_test = function() {
44804         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44805       };
44806       /**
44807        * @description Enable/disable uppercase hexadecimal returned string
44808        * @param {boolean}
44809        * @return {Object} this
44810        * @public
44811        */
44812       this.setUpperCase = function(a) {
44813         if (typeof a === 'boolean') {
44814           hexcase = a;
44815         }
44816         return this;
44817       };
44818       /**
44819        * @description Defines a base64 pad string
44820        * @param {string} Pad
44821        * @return {Object} this
44822        * @public
44823        */
44824       this.setPad = function(a) {
44825         b64pad = a || b64pad;
44826         return this;
44827       };
44828       /**
44829        * @description Defines a base64 pad string
44830        * @param {boolean}
44831        * @return {Object} this
44832        * @public
44833        */
44834       this.setUTF8 = function(a) {
44835         if (typeof a === 'boolean') {
44836           utf8 = a;
44837         }
44838         return this;
44839       };
44840
44841       /* private methods */
44842
44843       /**
44844        * Calculate the SHA-512 of a raw string
44845        */
44846
44847       function rstr(s) {
44848         s = (utf8) ? utf8Encode(s) : s;
44849         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44850       }
44851       /*
44852        * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
44853        */
44854
44855       function rstr_hmac(key, data) {
44856         key = (utf8) ? utf8Encode(key) : key;
44857         data = (utf8) ? utf8Encode(data) : data;
44858
44859         var hash, i = 0,
44860           bkey = rstr2binb(key),
44861           ipad = Array(32),
44862           opad = Array(32);
44863
44864         if (bkey.length > 32) {
44865           bkey = binb(bkey, key.length * 8);
44866         }
44867
44868         for (; i < 32; i += 1) {
44869           ipad[i] = bkey[i] ^ 0x36363636;
44870           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44871         }
44872
44873         hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
44874         return binb2rstr(binb(opad.concat(hash), 1024 + 512));
44875       }
44876
44877       /**
44878        * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
44879        */
44880
44881       function binb(x, len) {
44882         var j, i, l,
44883           W = new Array(80),
44884           hash = new Array(16),
44885           //Initial hash values
44886           H = [
44887             new int64(0x6a09e667, -205731576),
44888             new int64(-1150833019, -2067093701),
44889             new int64(0x3c6ef372, -23791573),
44890             new int64(-1521486534, 0x5f1d36f1),
44891             new int64(0x510e527f, -1377402159),
44892             new int64(-1694144372, 0x2b3e6c1f),
44893             new int64(0x1f83d9ab, -79577749),
44894             new int64(0x5be0cd19, 0x137e2179)
44895           ],
44896           T1 = new int64(0, 0),
44897           T2 = new int64(0, 0),
44898           a = new int64(0, 0),
44899           b = new int64(0, 0),
44900           c = new int64(0, 0),
44901           d = new int64(0, 0),
44902           e = new int64(0, 0),
44903           f = new int64(0, 0),
44904           g = new int64(0, 0),
44905           h = new int64(0, 0),
44906           //Temporary variables not specified by the document
44907           s0 = new int64(0, 0),
44908           s1 = new int64(0, 0),
44909           Ch = new int64(0, 0),
44910           Maj = new int64(0, 0),
44911           r1 = new int64(0, 0),
44912           r2 = new int64(0, 0),
44913           r3 = new int64(0, 0);
44914
44915         if (sha512_k === undefined) {
44916           //SHA512 constants
44917           sha512_k = [
44918             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
44919             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
44920             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
44921             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
44922             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
44923             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
44924             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
44925             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
44926             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
44927             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
44928             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
44929             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
44930             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
44931             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
44932             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
44933             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
44934             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
44935             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
44936             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
44937             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
44938             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
44939             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
44940             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
44941             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
44942             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
44943             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
44944             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
44945             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
44946             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
44947             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
44948             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
44949             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
44950             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
44951             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
44952             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
44953             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
44954             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
44955             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
44956             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
44957             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
44958           ];
44959         }
44960
44961         for (i = 0; i < 80; i += 1) {
44962           W[i] = new int64(0, 0);
44963         }
44964
44965         // append padding to the source string. The format is described in the FIPS.
44966         x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
44967         x[((len + 128 >> 10) << 5) + 31] = len;
44968         l = x.length;
44969         for (i = 0; i < l; i += 32) { //32 dwords is the block size
44970           int64copy(a, H[0]);
44971           int64copy(b, H[1]);
44972           int64copy(c, H[2]);
44973           int64copy(d, H[3]);
44974           int64copy(e, H[4]);
44975           int64copy(f, H[5]);
44976           int64copy(g, H[6]);
44977           int64copy(h, H[7]);
44978
44979           for (j = 0; j < 16; j += 1) {
44980             W[j].h = x[i + 2 * j];
44981             W[j].l = x[i + 2 * j + 1];
44982           }
44983
44984           for (j = 16; j < 80; j += 1) {
44985             //sigma1
44986             int64rrot(r1, W[j - 2], 19);
44987             int64revrrot(r2, W[j - 2], 29);
44988             int64shr(r3, W[j - 2], 6);
44989             s1.l = r1.l ^ r2.l ^ r3.l;
44990             s1.h = r1.h ^ r2.h ^ r3.h;
44991             //sigma0
44992             int64rrot(r1, W[j - 15], 1);
44993             int64rrot(r2, W[j - 15], 8);
44994             int64shr(r3, W[j - 15], 7);
44995             s0.l = r1.l ^ r2.l ^ r3.l;
44996             s0.h = r1.h ^ r2.h ^ r3.h;
44997
44998             int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
44999           }
45000
45001           for (j = 0; j < 80; j += 1) {
45002             //Ch
45003             Ch.l = (e.l & f.l) ^ (~e.l & g.l);
45004             Ch.h = (e.h & f.h) ^ (~e.h & g.h);
45005
45006             //Sigma1
45007             int64rrot(r1, e, 14);
45008             int64rrot(r2, e, 18);
45009             int64revrrot(r3, e, 9);
45010             s1.l = r1.l ^ r2.l ^ r3.l;
45011             s1.h = r1.h ^ r2.h ^ r3.h;
45012
45013             //Sigma0
45014             int64rrot(r1, a, 28);
45015             int64revrrot(r2, a, 2);
45016             int64revrrot(r3, a, 7);
45017             s0.l = r1.l ^ r2.l ^ r3.l;
45018             s0.h = r1.h ^ r2.h ^ r3.h;
45019
45020             //Maj
45021             Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
45022             Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
45023
45024             int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
45025             int64add(T2, s0, Maj);
45026
45027             int64copy(h, g);
45028             int64copy(g, f);
45029             int64copy(f, e);
45030             int64add(e, d, T1);
45031             int64copy(d, c);
45032             int64copy(c, b);
45033             int64copy(b, a);
45034             int64add(a, T1, T2);
45035           }
45036           int64add(H[0], H[0], a);
45037           int64add(H[1], H[1], b);
45038           int64add(H[2], H[2], c);
45039           int64add(H[3], H[3], d);
45040           int64add(H[4], H[4], e);
45041           int64add(H[5], H[5], f);
45042           int64add(H[6], H[6], g);
45043           int64add(H[7], H[7], h);
45044         }
45045
45046         //represent the hash as an array of 32-bit dwords
45047         for (i = 0; i < 8; i += 1) {
45048           hash[2 * i] = H[i].h;
45049           hash[2 * i + 1] = H[i].l;
45050         }
45051         return hash;
45052       }
45053
45054       //A constructor for 64-bit numbers
45055
45056       function int64(h, l) {
45057         this.h = h;
45058         this.l = l;
45059         //this.toString = int64toString;
45060       }
45061
45062       //Copies src into dst, assuming both are 64-bit numbers
45063
45064       function int64copy(dst, src) {
45065         dst.h = src.h;
45066         dst.l = src.l;
45067       }
45068
45069       //Right-rotates a 64-bit number by shift
45070       //Won't handle cases of shift>=32
45071       //The function revrrot() is for that
45072
45073       function int64rrot(dst, x, shift) {
45074         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45075         dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45076       }
45077
45078       //Reverses the dwords of the source and then rotates right by shift.
45079       //This is equivalent to rotation by 32+shift
45080
45081       function int64revrrot(dst, x, shift) {
45082         dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45083         dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45084       }
45085
45086       //Bitwise-shifts right a 64-bit number by shift
45087       //Won't handle shift>=32, but it's never needed in SHA512
45088
45089       function int64shr(dst, x, shift) {
45090         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45091         dst.h = (x.h >>> shift);
45092       }
45093
45094       //Adds two 64-bit numbers
45095       //Like the original implementation, does not rely on 32-bit operations
45096
45097       function int64add(dst, x, y) {
45098         var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45099         var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45100         var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45101         var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45102         dst.l = (w0 & 0xffff) | (w1 << 16);
45103         dst.h = (w2 & 0xffff) | (w3 << 16);
45104       }
45105
45106       //Same, except with 4 addends. Works faster than adding them one by one.
45107
45108       function int64add4(dst, a, b, c, d) {
45109         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45110         var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45111         var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45112         var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45113         dst.l = (w0 & 0xffff) | (w1 << 16);
45114         dst.h = (w2 & 0xffff) | (w3 << 16);
45115       }
45116
45117       //Same, except with 5 addends
45118
45119       function int64add5(dst, a, b, c, d, e) {
45120         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45121           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45122           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45123           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45124         dst.l = (w0 & 0xffff) | (w1 << 16);
45125         dst.h = (w2 & 0xffff) | (w3 << 16);
45126       }
45127     },
45128     /**
45129      * @class Hashes.RMD160
45130      * @constructor
45131      * @param {Object} [config]
45132      *
45133      * A JavaScript implementation of the RIPEMD-160 Algorithm
45134      * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45135      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45136      * See http://pajhome.org.uk/crypt/md5 for details.
45137      * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45138      */
45139     RMD160: function(options) {
45140       /**
45141        * Private properties configuration variables. You may need to tweak these to be compatible with
45142        * the server-side, but the defaults work in most cases.
45143        * @see this.setUpperCase() method
45144        * @see this.setPad() method
45145        */
45146       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45147         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45148         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45149         /* base-64 pad character. Default '=' for strict RFC compliance   */
45150         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45151         /* enable/disable utf8 encoding */
45152         rmd160_r1 = [
45153           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45154           7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45155           3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45156           1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45157           4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45158         ],
45159         rmd160_r2 = [
45160           5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45161           6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45162           15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45163           8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45164           12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45165         ],
45166         rmd160_s1 = [
45167           11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45168           7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45169           11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45170           11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45171           9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45172         ],
45173         rmd160_s2 = [
45174           8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45175           9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45176           9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45177           15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45178           8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45179         ];
45180
45181       /* privileged (public) methods */
45182       this.hex = function(s) {
45183         return rstr2hex(rstr(s, utf8));
45184       };
45185       this.b64 = function(s) {
45186         return rstr2b64(rstr(s, utf8), b64pad);
45187       };
45188       this.any = function(s, e) {
45189         return rstr2any(rstr(s, utf8), e);
45190       };
45191       this.raw = function(s) {
45192         return rstr(s, utf8);
45193       };
45194       this.hex_hmac = function(k, d) {
45195         return rstr2hex(rstr_hmac(k, d));
45196       };
45197       this.b64_hmac = function(k, d) {
45198         return rstr2b64(rstr_hmac(k, d), b64pad);
45199       };
45200       this.any_hmac = function(k, d, e) {
45201         return rstr2any(rstr_hmac(k, d), e);
45202       };
45203       /**
45204        * Perform a simple self-test to see if the VM is working
45205        * @return {String} Hexadecimal hash sample
45206        * @public
45207        */
45208       this.vm_test = function() {
45209         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45210       };
45211       /**
45212        * @description Enable/disable uppercase hexadecimal returned string
45213        * @param {boolean}
45214        * @return {Object} this
45215        * @public
45216        */
45217       this.setUpperCase = function(a) {
45218         if (typeof a === 'boolean') {
45219           hexcase = a;
45220         }
45221         return this;
45222       };
45223       /**
45224        * @description Defines a base64 pad string
45225        * @param {string} Pad
45226        * @return {Object} this
45227        * @public
45228        */
45229       this.setPad = function(a) {
45230         if (typeof a !== 'undefined') {
45231           b64pad = a;
45232         }
45233         return this;
45234       };
45235       /**
45236        * @description Defines a base64 pad string
45237        * @param {boolean}
45238        * @return {Object} this
45239        * @public
45240        */
45241       this.setUTF8 = function(a) {
45242         if (typeof a === 'boolean') {
45243           utf8 = a;
45244         }
45245         return this;
45246       };
45247
45248       /* private methods */
45249
45250       /**
45251        * Calculate the rmd160 of a raw string
45252        */
45253
45254       function rstr(s) {
45255         s = (utf8) ? utf8Encode(s) : s;
45256         return binl2rstr(binl(rstr2binl(s), s.length * 8));
45257       }
45258
45259       /**
45260        * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45261        */
45262
45263       function rstr_hmac(key, data) {
45264         key = (utf8) ? utf8Encode(key) : key;
45265         data = (utf8) ? utf8Encode(data) : data;
45266         var i, hash,
45267           bkey = rstr2binl(key),
45268           ipad = Array(16),
45269           opad = Array(16);
45270
45271         if (bkey.length > 16) {
45272           bkey = binl(bkey, key.length * 8);
45273         }
45274
45275         for (i = 0; i < 16; i += 1) {
45276           ipad[i] = bkey[i] ^ 0x36363636;
45277           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45278         }
45279         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45280         return binl2rstr(binl(opad.concat(hash), 512 + 160));
45281       }
45282
45283       /**
45284        * Convert an array of little-endian words to a string
45285        */
45286
45287       function binl2rstr(input) {
45288         var i, output = '',
45289           l = input.length * 32;
45290         for (i = 0; i < l; i += 8) {
45291           output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
45292         }
45293         return output;
45294       }
45295
45296       /**
45297        * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
45298        */
45299
45300       function binl(x, len) {
45301         var T, j, i, l,
45302           h0 = 0x67452301,
45303           h1 = 0xefcdab89,
45304           h2 = 0x98badcfe,
45305           h3 = 0x10325476,
45306           h4 = 0xc3d2e1f0,
45307           A1, B1, C1, D1, E1,
45308           A2, B2, C2, D2, E2;
45309
45310         /* append padding */
45311         x[len >> 5] |= 0x80 << (len % 32);
45312         x[(((len + 64) >>> 9) << 4) + 14] = len;
45313         l = x.length;
45314
45315         for (i = 0; i < l; i += 16) {
45316           A1 = A2 = h0;
45317           B1 = B2 = h1;
45318           C1 = C2 = h2;
45319           D1 = D2 = h3;
45320           E1 = E2 = h4;
45321           for (j = 0; j <= 79; j += 1) {
45322             T = safe_add(A1, rmd160_f(j, B1, C1, D1));
45323             T = safe_add(T, x[i + rmd160_r1[j]]);
45324             T = safe_add(T, rmd160_K1(j));
45325             T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
45326             A1 = E1;
45327             E1 = D1;
45328             D1 = bit_rol(C1, 10);
45329             C1 = B1;
45330             B1 = T;
45331             T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
45332             T = safe_add(T, x[i + rmd160_r2[j]]);
45333             T = safe_add(T, rmd160_K2(j));
45334             T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
45335             A2 = E2;
45336             E2 = D2;
45337             D2 = bit_rol(C2, 10);
45338             C2 = B2;
45339             B2 = T;
45340           }
45341
45342           T = safe_add(h1, safe_add(C1, D2));
45343           h1 = safe_add(h2, safe_add(D1, E2));
45344           h2 = safe_add(h3, safe_add(E1, A2));
45345           h3 = safe_add(h4, safe_add(A1, B2));
45346           h4 = safe_add(h0, safe_add(B1, C2));
45347           h0 = T;
45348         }
45349         return [h0, h1, h2, h3, h4];
45350       }
45351
45352       // specific algorithm methods
45353
45354       function rmd160_f(j, x, y, z) {
45355         return (0 <= j && j <= 15) ? (x ^ y ^ z) :
45356           (16 <= j && j <= 31) ? (x & y) | (~x & z) :
45357           (32 <= j && j <= 47) ? (x | ~y) ^ z :
45358           (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
45359           (64 <= j && j <= 79) ? x ^ (y | ~z) :
45360           'rmd160_f: j out of range';
45361       }
45362
45363       function rmd160_K1(j) {
45364         return (0 <= j && j <= 15) ? 0x00000000 :
45365           (16 <= j && j <= 31) ? 0x5a827999 :
45366           (32 <= j && j <= 47) ? 0x6ed9eba1 :
45367           (48 <= j && j <= 63) ? 0x8f1bbcdc :
45368           (64 <= j && j <= 79) ? 0xa953fd4e :
45369           'rmd160_K1: j out of range';
45370       }
45371
45372       function rmd160_K2(j) {
45373         return (0 <= j && j <= 15) ? 0x50a28be6 :
45374           (16 <= j && j <= 31) ? 0x5c4dd124 :
45375           (32 <= j && j <= 47) ? 0x6d703ef3 :
45376           (48 <= j && j <= 63) ? 0x7a6d76e9 :
45377           (64 <= j && j <= 79) ? 0x00000000 :
45378           'rmd160_K2: j out of range';
45379       }
45380     }
45381   };
45382
45383   // exposes Hashes
45384   (function(window, undefined) {
45385     var freeExports = false;
45386     if (typeof exports === 'object') {
45387       freeExports = exports;
45388       if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
45389         window = commonjsGlobal;
45390       }
45391     }
45392
45393     if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
45394       // define as an anonymous module, so, through path mapping, it can be aliased
45395       define(function() {
45396         return Hashes;
45397       });
45398     } else if (freeExports) {
45399       // in Node.js or RingoJS v0.8.0+
45400       if (typeof module === 'object' && module && module.exports === freeExports) {
45401         module.exports = Hashes;
45402       }
45403       // in Narwhal or RingoJS v0.7.0-
45404       else {
45405         freeExports.Hashes = Hashes;
45406       }
45407     } else {
45408       // in a browser or Rhino
45409       window.Hashes = Hashes;
45410     }
45411   }(this));
45412 }()); // IIFE
45413 });
45414
45415 var immutable = extend$2;
45416
45417 var hasOwnProperty = Object.prototype.hasOwnProperty;
45418
45419 function extend$2() {
45420     var target = {};
45421
45422     for (var i = 0; i < arguments.length; i++) {
45423         var source = arguments[i];
45424
45425         for (var key in source) {
45426             if (hasOwnProperty.call(source, key)) {
45427                 target[key] = source[key];
45428             }
45429         }
45430     }
45431
45432     return target
45433 }
45434
45435 var hashes = hashes$1;
45436 var xtend$1 = immutable;
45437 var sha1 = new hashes.SHA1();
45438
45439 var ohauth$1 = {};
45440
45441 ohauth$1.qsString = function(obj) {
45442     return Object.keys(obj).sort().map(function(key) {
45443         return ohauth$1.percentEncode(key) + '=' +
45444             ohauth$1.percentEncode(obj[key]);
45445     }).join('&');
45446 };
45447
45448 ohauth$1.stringQs = function(str) {
45449     return str.split('&').filter(function (pair) {
45450         return pair !== '';
45451     }).reduce(function(obj, pair){
45452         var parts = pair.split('=');
45453         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
45454             '' : decodeURIComponent(parts[1]);
45455         return obj;
45456     }, {});
45457 };
45458
45459 ohauth$1.rawxhr = function(method, url, data, headers, callback) {
45460     var xhr = new XMLHttpRequest(),
45461         twoHundred = /^20\d$/;
45462     xhr.onreadystatechange = function() {
45463         if (4 === xhr.readyState && 0 !== xhr.status) {
45464             if (twoHundred.test(xhr.status)) callback(null, xhr);
45465             else return callback(xhr, null);
45466         }
45467     };
45468     xhr.onerror = function(e) { return callback(e, null); };
45469     xhr.open(method, url, true);
45470     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
45471     xhr.send(data);
45472     return xhr;
45473 };
45474
45475 ohauth$1.xhr = function(method, url, auth, data, options, callback) {
45476     var headers = (options && options.header) || {
45477         'Content-Type': 'application/x-www-form-urlencoded'
45478     };
45479     headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
45480     return ohauth$1.rawxhr(method, url, data, headers, callback);
45481 };
45482
45483 ohauth$1.nonce = function() {
45484     for (var o = ''; o.length < 6;) {
45485         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
45486     }
45487     return o;
45488 };
45489
45490 ohauth$1.authHeader = function(obj) {
45491     return Object.keys(obj).sort().map(function(key) {
45492         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
45493     }).join(', ');
45494 };
45495
45496 ohauth$1.timestamp = function() { return ~~((+new Date()) / 1000); };
45497
45498 ohauth$1.percentEncode = function(s) {
45499     return encodeURIComponent(s)
45500         .replace(/\!/g, '%21').replace(/\'/g, '%27')
45501         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
45502 };
45503
45504 ohauth$1.baseString = function(method, url, params) {
45505     if (params.oauth_signature) delete params.oauth_signature;
45506     return [
45507         method,
45508         ohauth$1.percentEncode(url),
45509         ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
45510 };
45511
45512 ohauth$1.signature = function(oauth_secret, token_secret, baseString) {
45513     return sha1.b64_hmac(
45514         ohauth$1.percentEncode(oauth_secret) + '&' +
45515         ohauth$1.percentEncode(token_secret),
45516         baseString);
45517 };
45518
45519 /**
45520  * Takes an options object for configuration (consumer_key,
45521  * consumer_secret, version, signature_method, token, token_secret)
45522  * and returns a function that generates the Authorization header
45523  * for given data.
45524  *
45525  * The returned function takes these parameters:
45526  * - method: GET/POST/...
45527  * - uri: full URI with protocol, port, path and query string
45528  * - extra_params: any extra parameters (that are passed in the POST data),
45529  *   can be an object or a from-urlencoded string.
45530  *
45531  * Returned function returns full OAuth header with "OAuth" string in it.
45532  */
45533
45534 ohauth$1.headerGenerator = function(options) {
45535     options = options || {};
45536     var consumer_key = options.consumer_key || '',
45537         consumer_secret = options.consumer_secret || '',
45538         signature_method = options.signature_method || 'HMAC-SHA1',
45539         version = options.version || '1.0',
45540         token = options.token || '',
45541         token_secret = options.token_secret || '';
45542
45543     return function(method, uri, extra_params) {
45544         method = method.toUpperCase();
45545         if (typeof extra_params === 'string' && extra_params.length > 0) {
45546             extra_params = ohauth$1.stringQs(extra_params);
45547         }
45548
45549         var uri_parts = uri.split('?', 2),
45550         base_uri = uri_parts[0];
45551
45552         var query_params = uri_parts.length === 2 ?
45553             ohauth$1.stringQs(uri_parts[1]) : {};
45554
45555         var oauth_params = {
45556             oauth_consumer_key: consumer_key,
45557             oauth_signature_method: signature_method,
45558             oauth_version: version,
45559             oauth_timestamp: ohauth$1.timestamp(),
45560             oauth_nonce: ohauth$1.nonce()
45561         };
45562
45563         if (token) oauth_params.oauth_token = token;
45564
45565         var all_params = xtend$1({}, oauth_params, query_params, extra_params),
45566             base_str = ohauth$1.baseString(method, base_uri, all_params);
45567
45568         oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
45569
45570         return 'OAuth ' + ohauth$1.authHeader(oauth_params);
45571     };
45572 };
45573
45574 var index$12 = ohauth$1;
45575
45576 var store$1 = createCommonjsModule(function (module, exports) {
45577 "use strict"
45578 // Module export pattern from
45579 // https://github.com/umdjs/umd/blob/master/returnExports.js
45580 ;(function (root, factory) {
45581     if (typeof define === 'function' && define.amd) {
45582         // AMD. Register as an anonymous module.
45583         define([], factory);
45584     } else if (typeof exports === 'object') {
45585         // Node. Does not work with strict CommonJS, but
45586         // only CommonJS-like environments that support module.exports,
45587         // like Node.
45588         module.exports = factory();
45589     } else {
45590         // Browser globals (root is window)
45591         root.store = factory();
45592   }
45593 }(commonjsGlobal, function () {
45594         
45595         // Store.js
45596         var store = {},
45597                 win = (typeof window != 'undefined' ? window : commonjsGlobal),
45598                 doc = win.document,
45599                 localStorageName = 'localStorage',
45600                 scriptTag = 'script',
45601                 storage;
45602
45603         store.disabled = false;
45604         store.version = '1.3.20';
45605         store.set = function(key, value) {};
45606         store.get = function(key, defaultVal) {};
45607         store.has = function(key) { return store.get(key) !== undefined };
45608         store.remove = function(key) {};
45609         store.clear = function() {};
45610         store.transact = function(key, defaultVal, transactionFn) {
45611                 if (transactionFn == null) {
45612                         transactionFn = defaultVal;
45613                         defaultVal = null;
45614                 }
45615                 if (defaultVal == null) {
45616                         defaultVal = {};
45617                 }
45618                 var val = store.get(key, defaultVal);
45619                 transactionFn(val);
45620                 store.set(key, val);
45621         };
45622         store.getAll = function() {};
45623         store.forEach = function() {};
45624
45625         store.serialize = function(value) {
45626                 return JSON.stringify(value)
45627         };
45628         store.deserialize = function(value) {
45629                 if (typeof value != 'string') { return undefined }
45630                 try { return JSON.parse(value) }
45631                 catch(e) { return value || undefined }
45632         };
45633
45634         // Functions to encapsulate questionable FireFox 3.6.13 behavior
45635         // when about.config::dom.storage.enabled === false
45636         // See https://github.com/marcuswestin/store.js/issues#issue/13
45637         function isLocalStorageNameSupported() {
45638                 try { return (localStorageName in win && win[localStorageName]) }
45639                 catch(err) { return false }
45640         }
45641
45642         if (isLocalStorageNameSupported()) {
45643                 storage = win[localStorageName];
45644                 store.set = function(key, val) {
45645                         if (val === undefined) { return store.remove(key) }
45646                         storage.setItem(key, store.serialize(val));
45647                         return val
45648                 };
45649                 store.get = function(key, defaultVal) {
45650                         var val = store.deserialize(storage.getItem(key));
45651                         return (val === undefined ? defaultVal : val)
45652                 };
45653                 store.remove = function(key) { storage.removeItem(key); };
45654                 store.clear = function() { storage.clear(); };
45655                 store.getAll = function() {
45656                         var ret = {};
45657                         store.forEach(function(key, val) {
45658                                 ret[key] = val;
45659                         });
45660                         return ret
45661                 };
45662                 store.forEach = function(callback) {
45663                         for (var i=0; i<storage.length; i++) {
45664                                 var key = storage.key(i);
45665                                 callback(key, store.get(key));
45666                         }
45667                 };
45668         } else if (doc && doc.documentElement.addBehavior) {
45669                 var storageOwner,
45670                         storageContainer;
45671                 // Since #userData storage applies only to specific paths, we need to
45672                 // somehow link our data to a specific path.  We choose /favicon.ico
45673                 // as a pretty safe option, since all browsers already make a request to
45674                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
45675                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
45676                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
45677                 // since the iframe access rules appear to allow direct access and
45678                 // manipulation of the document element, even for a 404 page.  This
45679                 // document can be used instead of the current document (which would
45680                 // have been limited to the current path) to perform #userData storage.
45681                 try {
45682                         storageContainer = new ActiveXObject('htmlfile');
45683                         storageContainer.open();
45684                         storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
45685                         storageContainer.close();
45686                         storageOwner = storageContainer.w.frames[0].document;
45687                         storage = storageOwner.createElement('div');
45688                 } catch(e) {
45689                         // somehow ActiveXObject instantiation failed (perhaps some special
45690                         // security settings or otherwse), fall back to per-path storage
45691                         storage = doc.createElement('div');
45692                         storageOwner = doc.body;
45693                 }
45694                 var withIEStorage = function(storeFunction) {
45695                         return function() {
45696                                 var args = Array.prototype.slice.call(arguments, 0);
45697                                 args.unshift(storage);
45698                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
45699                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
45700                                 storageOwner.appendChild(storage);
45701                                 storage.addBehavior('#default#userData');
45702                                 storage.load(localStorageName);
45703                                 var result = storeFunction.apply(store, args);
45704                                 storageOwner.removeChild(storage);
45705                                 return result
45706                         }
45707                 };
45708
45709                 // In IE7, keys cannot start with a digit or contain certain chars.
45710                 // See https://github.com/marcuswestin/store.js/issues/40
45711                 // See https://github.com/marcuswestin/store.js/issues/83
45712                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
45713                 var ieKeyFix = function(key) {
45714                         return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
45715                 };
45716                 store.set = withIEStorage(function(storage, key, val) {
45717                         key = ieKeyFix(key);
45718                         if (val === undefined) { return store.remove(key) }
45719                         storage.setAttribute(key, store.serialize(val));
45720                         storage.save(localStorageName);
45721                         return val
45722                 });
45723                 store.get = withIEStorage(function(storage, key, defaultVal) {
45724                         key = ieKeyFix(key);
45725                         var val = store.deserialize(storage.getAttribute(key));
45726                         return (val === undefined ? defaultVal : val)
45727                 });
45728                 store.remove = withIEStorage(function(storage, key) {
45729                         key = ieKeyFix(key);
45730                         storage.removeAttribute(key);
45731                         storage.save(localStorageName);
45732                 });
45733                 store.clear = withIEStorage(function(storage) {
45734                         var attributes = storage.XMLDocument.documentElement.attributes;
45735                         storage.load(localStorageName);
45736                         for (var i=attributes.length-1; i>=0; i--) {
45737                                 storage.removeAttribute(attributes[i].name);
45738                         }
45739                         storage.save(localStorageName);
45740                 });
45741                 store.getAll = function(storage) {
45742                         var ret = {};
45743                         store.forEach(function(key, val) {
45744                                 ret[key] = val;
45745                         });
45746                         return ret
45747                 };
45748                 store.forEach = withIEStorage(function(storage, callback) {
45749                         var attributes = storage.XMLDocument.documentElement.attributes;
45750                         for (var i=0, attr; attr=attributes[i]; ++i) {
45751                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
45752                         }
45753                 });
45754         }
45755
45756         try {
45757                 var testKey = '__storejs__';
45758                 store.set(testKey, testKey);
45759                 if (store.get(testKey) != testKey) { store.disabled = true; }
45760                 store.remove(testKey);
45761         } catch(e) {
45762                 store.disabled = true;
45763         }
45764         store.enabled = !store.disabled;
45765         
45766         return store
45767 }));
45768 });
45769
45770 var ohauth = index$12;
45771 var xtend = immutable;
45772 var store = store$1;
45773
45774 // # osm-auth
45775 //
45776 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
45777 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
45778 // does not support custom headers, which this uses everywhere.
45779 var index$11 = function(o) {
45780
45781     var oauth = {};
45782
45783     // authenticated users will also have a request token secret, but it's
45784     // not used in transactions with the server
45785     oauth.authenticated = function() {
45786         return !!(token('oauth_token') && token('oauth_token_secret'));
45787     };
45788
45789     oauth.logout = function() {
45790         token('oauth_token', '');
45791         token('oauth_token_secret', '');
45792         token('oauth_request_token_secret', '');
45793         return oauth;
45794     };
45795
45796     // TODO: detect lack of click event
45797     oauth.authenticate = function(callback) {
45798         if (oauth.authenticated()) return callback();
45799
45800         oauth.logout();
45801
45802         // ## Getting a request token
45803         var params = timenonce(getAuth(o)),
45804             url = o.url + '/oauth/request_token';
45805
45806         params.oauth_signature = ohauth.signature(
45807             o.oauth_secret, '',
45808             ohauth.baseString('POST', url, params));
45809
45810         if (!o.singlepage) {
45811             // Create a 600x550 popup window in the center of the screen
45812             var w = 600, h = 550,
45813                 settings = [
45814                     ['width', w], ['height', h],
45815                     ['left', screen.width / 2 - w / 2],
45816                     ['top', screen.height / 2 - h / 2]].map(function(x) {
45817                         return x.join('=');
45818                     }).join(','),
45819                 popup = window.open('about:blank', 'oauth_window', settings);
45820         }
45821
45822         // Request a request token. When this is complete, the popup
45823         // window is redirected to OSM's authorization page.
45824         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
45825         o.loading();
45826
45827         function reqTokenDone(err, xhr) {
45828             o.done();
45829             if (err) return callback(err);
45830             var resp = ohauth.stringQs(xhr.response);
45831             token('oauth_request_token_secret', resp.oauth_token_secret);
45832             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
45833                 oauth_token: resp.oauth_token,
45834                 oauth_callback: location.href.replace('index.html', '')
45835                     .replace(/#.*/, '').replace(location.search, '') + o.landing
45836             });
45837
45838             if (o.singlepage) {
45839                 location.href = authorize_url;
45840             } else {
45841                 popup.location = authorize_url;
45842             }
45843         }
45844
45845         // Called by a function in a landing page, in the popup window. The
45846         // window closes itself.
45847         window.authComplete = function(token) {
45848             var oauth_token = ohauth.stringQs(token.split('?')[1]);
45849             get_access_token(oauth_token.oauth_token);
45850             delete window.authComplete;
45851         };
45852
45853         // ## Getting an request token
45854         //
45855         // At this point we have an `oauth_token`, brought in from a function
45856         // call on a landing page popup.
45857         function get_access_token(oauth_token) {
45858             var url = o.url + '/oauth/access_token',
45859                 params = timenonce(getAuth(o)),
45860                 request_token_secret = token('oauth_request_token_secret');
45861             params.oauth_token = oauth_token;
45862             params.oauth_signature = ohauth.signature(
45863                 o.oauth_secret,
45864                 request_token_secret,
45865                 ohauth.baseString('POST', url, params));
45866
45867             // ## Getting an access token
45868             //
45869             // The final token required for authentication. At this point
45870             // we have a `request token secret`
45871             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
45872             o.loading();
45873         }
45874
45875         function accessTokenDone(err, xhr) {
45876             o.done();
45877             if (err) return callback(err);
45878             var access_token = ohauth.stringQs(xhr.response);
45879             token('oauth_token', access_token.oauth_token);
45880             token('oauth_token_secret', access_token.oauth_token_secret);
45881             callback(null, oauth);
45882         }
45883     };
45884
45885     oauth.bootstrapToken = function(oauth_token, callback) {
45886         // ## Getting an request token
45887         // At this point we have an `oauth_token`, brought in from a function
45888         // call on a landing page popup.
45889         function get_access_token(oauth_token) {
45890             var url = o.url + '/oauth/access_token',
45891                 params = timenonce(getAuth(o)),
45892                 request_token_secret = token('oauth_request_token_secret');
45893             params.oauth_token = oauth_token;
45894             params.oauth_signature = ohauth.signature(
45895                 o.oauth_secret,
45896                 request_token_secret,
45897                 ohauth.baseString('POST', url, params));
45898
45899             // ## Getting an access token
45900             // The final token required for authentication. At this point
45901             // we have a `request token secret`
45902             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
45903             o.loading();
45904         }
45905
45906         function accessTokenDone(err, xhr) {
45907             o.done();
45908             if (err) return callback(err);
45909             var access_token = ohauth.stringQs(xhr.response);
45910             token('oauth_token', access_token.oauth_token);
45911             token('oauth_token_secret', access_token.oauth_token_secret);
45912             callback(null, oauth);
45913         }
45914
45915         get_access_token(oauth_token);
45916     };
45917
45918     // # xhr
45919     //
45920     // A single XMLHttpRequest wrapper that does authenticated calls if the
45921     // user has logged in.
45922     oauth.xhr = function(options, callback) {
45923         if (!oauth.authenticated()) {
45924             if (o.auto) {
45925                 return oauth.authenticate(run);
45926             } else {
45927                 callback('not authenticated', null);
45928                 return;
45929             }
45930         } else {
45931             return run();
45932         }
45933
45934         function run() {
45935             var params = timenonce(getAuth(o)),
45936                 oauth_token_secret = token('oauth_token_secret'),
45937                 url = (options.prefix !== false) ? o.url + options.path : options.path,
45938                 url_parts = url.replace(/#.*$/, '').split('?', 2),
45939                 base_url = url_parts[0],
45940                 query = (url_parts.length === 2) ? url_parts[1] : '';
45941
45942             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
45943             if ((!options.options || !options.options.header ||
45944                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
45945                 options.content) {
45946                 params = xtend(params, ohauth.stringQs(options.content));
45947             }
45948
45949             params.oauth_token = token('oauth_token');
45950             params.oauth_signature = ohauth.signature(
45951                 o.oauth_secret,
45952                 oauth_token_secret,
45953                 ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query)))
45954             );
45955
45956             return ohauth.xhr(options.method, url, params, options.content, options.options, done);
45957         }
45958
45959         function done(err, xhr) {
45960             if (err) return callback(err);
45961             else if (xhr.responseXML) return callback(err, xhr.responseXML);
45962             else return callback(err, xhr.response);
45963         }
45964     };
45965
45966     // pre-authorize this object, if we can just get a token and token_secret
45967     // from the start
45968     oauth.preauth = function(c) {
45969         if (!c) return;
45970         if (c.oauth_token) token('oauth_token', c.oauth_token);
45971         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
45972         return oauth;
45973     };
45974
45975     oauth.options = function(_) {
45976         if (!arguments.length) return o;
45977
45978         o = _;
45979         o.url = o.url || 'http://www.openstreetmap.org';
45980         o.landing = o.landing || 'land.html';
45981         o.singlepage = o.singlepage || false;
45982
45983         // Optional loading and loading-done functions for nice UI feedback.
45984         // by default, no-ops
45985         o.loading = o.loading || function() {};
45986         o.done = o.done || function() {};
45987
45988         return oauth.preauth(o);
45989     };
45990
45991     // 'stamp' an authentication object from `getAuth()`
45992     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
45993     // and timestamp
45994     function timenonce(o) {
45995         o.oauth_timestamp = ohauth.timestamp();
45996         o.oauth_nonce = ohauth.nonce();
45997         return o;
45998     }
45999
46000     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
46001     // can be used with multiple APIs and the keys in `localStorage`
46002     // will not clash
46003     var token;
46004
46005     if (store.enabled) {
46006         token = function (x, y) {
46007             if (arguments.length === 1) return store.get(o.url + x);
46008             else if (arguments.length === 2) return store.set(o.url + x, y);
46009         };
46010     } else {
46011         var storage = {};
46012         token = function (x, y) {
46013             if (arguments.length === 1) return storage[o.url + x];
46014             else if (arguments.length === 2) return storage[o.url + x] = y;
46015         };
46016     }
46017
46018     // Get an authentication object. If you just add and remove properties
46019     // from a single object, you'll need to use `delete` to make sure that
46020     // it doesn't contain undesired properties for authentication
46021     function getAuth(o) {
46022         return {
46023             oauth_consumer_key: o.oauth_consumer_key,
46024             oauth_signature_method: 'HMAC-SHA1'
46025         };
46026     }
46027
46028     // potentially pre-authorize
46029     oauth.options(o);
46030
46031     return oauth;
46032 };
46033
46034 var JXON = new (function () {
46035   var
46036     sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
46037     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
46038
46039   function parseText (sValue) {
46040     if (rIsNull.test(sValue)) { return null; }
46041     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
46042     if (isFinite(sValue)) { return parseFloat(sValue); }
46043     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
46044     return sValue;
46045   }
46046
46047   function EmptyTree () { }
46048   EmptyTree.prototype.toString = function () { return 'null'; };
46049   EmptyTree.prototype.valueOf = function () { return null; };
46050
46051   function objectify (vValue) {
46052     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
46053   }
46054
46055   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
46056     var
46057       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
46058       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
46059
46060     var
46061       sProp, vContent, nLength = 0, sCollectedTxt = '',
46062       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46063
46064     if (bChildren) {
46065       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46066         oNode = oParentNode.childNodes.item(nItem);
46067         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46068         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46069         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46070       }
46071     }
46072
46073     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46074
46075     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46076
46077     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46078       sProp = aCache[nElId].nodeName.toLowerCase();
46079       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46080       if (vResult.hasOwnProperty(sProp)) {
46081         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46082         vResult[sProp].push(vContent);
46083       } else {
46084         vResult[sProp] = vContent;
46085         nLength++;
46086       }
46087     }
46088
46089     if (bAttributes) {
46090       var
46091         nAttrLen = oParentNode.attributes.length,
46092         sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46093
46094       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46095         oAttrib = oParentNode.attributes.item(nAttrib);
46096         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46097       }
46098
46099       if (bNesteAttr) {
46100         if (bFreeze) { Object.freeze(oAttrParent); }
46101         vResult[sAttributesProp] = oAttrParent;
46102         nLength -= nAttrLen - 1;
46103       }
46104     }
46105
46106     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46107       vResult[sValueProp] = vBuiltVal;
46108     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46109       vResult = vBuiltVal;
46110     }
46111
46112     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46113
46114     aCache.length = nLevelStart;
46115
46116     return vResult;
46117   }
46118
46119   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46120     var vValue, oChild;
46121
46122     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46123       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46124     } else if (oParentObj.constructor === Date) {
46125       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
46126     }
46127
46128     for (var sName in oParentObj) {
46129       vValue = oParentObj[sName];
46130       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46131       if (sName === sValueProp) {
46132         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46133       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46134         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46135       } else if (sName.charAt(0) === sAttrPref) {
46136         oParentEl.setAttribute(sName.slice(1), vValue);
46137       } else if (vValue.constructor === Array) {
46138         for (var nItem = 0; nItem < vValue.length; nItem++) {
46139           oChild = oXMLDoc.createElement(sName);
46140           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46141           oParentEl.appendChild(oChild);
46142         }
46143       } else {
46144         oChild = oXMLDoc.createElement(sName);
46145         if (vValue instanceof Object) {
46146           loadObjTree(oXMLDoc, oChild, vValue);
46147         } else if (vValue !== null && vValue !== true) {
46148           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46149         }
46150         oParentEl.appendChild(oChild);
46151      }
46152    }
46153   }
46154
46155   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46156     var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46157     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
46158   };
46159
46160   this.unbuild = function (oObjTree) {    
46161     var oNewDoc = document.implementation.createDocument('', '', null);
46162     loadObjTree(oNewDoc, oNewDoc, oObjTree);
46163     return oNewDoc;
46164   };
46165
46166   this.stringify = function (oObjTree) {
46167     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46168   };
46169 })();
46170
46171 // var myObject = JXON.build(doc);
46172 // we got our javascript object! try: alert(JSON.stringify(myObject));
46173
46174 // var newDoc = JXON.unbuild(myObject);
46175 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46176
46177 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46178 var useHttps = window.location.protocol === 'https:';
46179 var protocol = useHttps ? 'https:' : 'http:';
46180 var urlroot = protocol + '//www.openstreetmap.org';
46181 var blacklists = ['.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*'];
46182 var inflight = {};
46183 var loadedTiles = {};
46184 var tileZoom$1 = 16;
46185 var oauth = index$11({
46186         url: urlroot,
46187         oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46188         oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46189         loading: authLoading,
46190         done: authDone
46191     });
46192 var rateLimitError;
46193 var userDetails;
46194 var off;
46195
46196
46197 function authLoading() {
46198     dispatch$3.call('authLoading');
46199 }
46200
46201
46202 function authDone() {
46203     dispatch$3.call('authDone');
46204 }
46205
46206
46207 function abortRequest$1(i) {
46208     if (i) {
46209         i.abort();
46210     }
46211 }
46212
46213
46214 function getLoc(attrs) {
46215     var lon = attrs.lon && attrs.lon.value,
46216         lat = attrs.lat && attrs.lat.value;
46217     return [parseFloat(lon), parseFloat(lat)];
46218 }
46219
46220
46221 function getNodes(obj) {
46222     var elems = obj.getElementsByTagName('nd'),
46223         nodes = new Array(elems.length);
46224     for (var i = 0, l = elems.length; i < l; i++) {
46225         nodes[i] = 'n' + elems[i].attributes.ref.value;
46226     }
46227     return nodes;
46228 }
46229
46230
46231 function getTags(obj) {
46232     var elems = obj.getElementsByTagName('tag'),
46233         tags = {};
46234     for (var i = 0, l = elems.length; i < l; i++) {
46235         var attrs = elems[i].attributes;
46236         tags[attrs.k.value] = attrs.v.value;
46237     }
46238     return tags;
46239 }
46240
46241
46242 function getMembers(obj) {
46243     var elems = obj.getElementsByTagName('member'),
46244         members = new Array(elems.length);
46245     for (var i = 0, l = elems.length; i < l; i++) {
46246         var attrs = elems[i].attributes;
46247         members[i] = {
46248             id: attrs.type.value[0] + attrs.ref.value,
46249             type: attrs.type.value,
46250             role: attrs.role.value
46251         };
46252     }
46253     return members;
46254 }
46255
46256
46257 function getVisible(attrs) {
46258     return (!attrs.visible || attrs.visible.value !== 'false');
46259 }
46260
46261
46262 var parsers = {
46263     node: function nodeData(obj) {
46264         var attrs = obj.attributes;
46265         return new osmNode({
46266             id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46267             loc: getLoc(attrs),
46268             version: attrs.version.value,
46269             user: attrs.user && attrs.user.value,
46270             tags: getTags(obj),
46271             visible: getVisible(attrs)
46272         });
46273     },
46274
46275     way: function wayData(obj) {
46276         var attrs = obj.attributes;
46277         return new osmWay({
46278             id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46279             version: attrs.version.value,
46280             user: attrs.user && attrs.user.value,
46281             tags: getTags(obj),
46282             nodes: getNodes(obj),
46283             visible: getVisible(attrs)
46284         });
46285     },
46286
46287     relation: function relationData(obj) {
46288         var attrs = obj.attributes;
46289         return new osmRelation({
46290             id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
46291             version: attrs.version.value,
46292             user: attrs.user && attrs.user.value,
46293             tags: getTags(obj),
46294             members: getMembers(obj),
46295             visible: getVisible(attrs)
46296         });
46297     }
46298 };
46299
46300
46301 function parse(xml$$1) {
46302     if (!xml$$1 || !xml$$1.childNodes) return;
46303
46304     var root = xml$$1.childNodes[0],
46305         children = root.childNodes,
46306         entities = [];
46307
46308     for (var i = 0, l = children.length; i < l; i++) {
46309         var child = children[i],
46310             parser = parsers[child.nodeName];
46311         if (parser) {
46312             entities.push(parser(child));
46313         }
46314     }
46315
46316     return entities;
46317 }
46318
46319
46320 var serviceOsm = {
46321
46322     init: function() {
46323         utilRebind(this, dispatch$3, 'on');
46324     },
46325
46326
46327     reset: function() {
46328         userDetails = undefined;
46329         rateLimitError = undefined;
46330         lodash.forEach(inflight, abortRequest$1);
46331         loadedTiles = {};
46332         inflight = {};
46333         return this;
46334     },
46335
46336
46337     changesetURL: function(changesetId) {
46338         return urlroot + '/changeset/' + changesetId;
46339     },
46340
46341
46342     changesetsURL: function(center, zoom$$1) {
46343         var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
46344         return urlroot + '/history#map=' +
46345             Math.floor(zoom$$1) + '/' +
46346             center[1].toFixed(precision) + '/' +
46347             center[0].toFixed(precision);
46348     },
46349
46350
46351     entityURL: function(entity) {
46352         return urlroot + '/' + entity.type + '/' + entity.osmId();
46353     },
46354
46355
46356     userURL: function(username) {
46357         return urlroot + '/user/' + username;
46358     },
46359
46360
46361     loadFromAPI: function(path$$1, callback) {
46362         var that = this;
46363
46364         function done(err, xml$$1) {
46365             var isAuthenticated = that.authenticated();
46366
46367             // 400 Bad Request, 401 Unauthorized, 403 Forbidden
46368             // Logout and retry the request..
46369             if (isAuthenticated && err &&
46370                     (err.status === 400 || err.status === 401 || err.status === 403)) {
46371                 that.logout();
46372                 that.loadFromAPI(path$$1, callback);
46373
46374             // else, no retry..
46375             } else {
46376                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
46377                 // Set the rateLimitError flag and trigger a warning..
46378                 if (!isAuthenticated && !rateLimitError && err &&
46379                         (err.status === 509 || err.status === 429)) {
46380                     rateLimitError = err;
46381                     dispatch$3.call('change');
46382                 }
46383
46384                 if (callback) {
46385                     callback(err, parse(xml$$1));
46386                 }
46387             }
46388         }
46389
46390         if (this.authenticated()) {
46391             return oauth.xhr({ method: 'GET', path: path$$1 }, done);
46392         } else {
46393             var url = urlroot + path$$1;
46394             return xml(url).get(done);
46395         }
46396     },
46397
46398
46399     loadEntity: function(id, callback) {
46400         var type = osmEntity$$1.id.type(id),
46401             osmID = osmEntity$$1.id.toOSM(id);
46402
46403         this.loadFromAPI(
46404             '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
46405             function(err, entities) {
46406                 if (callback) callback(err, { data: entities });
46407             }
46408         );
46409     },
46410
46411
46412     loadEntityVersion: function(id, version$$1, callback) {
46413         var type = osmEntity$$1.id.type(id),
46414             osmID = osmEntity$$1.id.toOSM(id);
46415
46416         this.loadFromAPI(
46417             '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
46418             function(err, entities) {
46419                 if (callback) callback(err, { data: entities });
46420             }
46421         );
46422     },
46423
46424
46425     loadMultiple: function(ids, callback) {
46426         var that = this;
46427         lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
46428             var type = k + 's',
46429                 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
46430
46431             lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
46432                 that.loadFromAPI(
46433                     '/api/0.6/' + type + '?' + type + '=' + arr.join(),
46434                     function(err, entities) {
46435                         if (callback) callback(err, { data: entities });
46436                     }
46437                 );
46438             });
46439         });
46440     },
46441
46442
46443     authenticated: function() {
46444         return oauth.authenticated();
46445     },
46446
46447
46448     // Generate Changeset XML. Returns a string.
46449     changesetJXON: function(tags) {
46450         return {
46451             osm: {
46452                 changeset: {
46453                     tag: lodash.map(tags, function(value, key) {
46454                         return { '@k': key, '@v': value };
46455                     }),
46456                     '@version': 0.6,
46457                     '@generator': 'iD'
46458                 }
46459             }
46460         };
46461     },
46462
46463
46464     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
46465     // XML. Returns a string.
46466     osmChangeJXON: function(changeset_id, changes) {
46467         function nest$$1(x, order) {
46468             var groups = {};
46469             for (var i = 0; i < x.length; i++) {
46470                 var tagName = Object.keys(x[i])[0];
46471                 if (!groups[tagName]) groups[tagName] = [];
46472                 groups[tagName].push(x[i][tagName]);
46473             }
46474             var ordered = {};
46475             order.forEach(function(o) {
46476                 if (groups[o]) ordered[o] = groups[o];
46477             });
46478             return ordered;
46479         }
46480
46481         function rep(entity) {
46482             return entity.asJXON(changeset_id);
46483         }
46484
46485         return {
46486             osmChange: {
46487                 '@version': 0.6,
46488                 '@generator': 'iD',
46489                 'create': nest$$1(changes.created.map(rep), ['node', 'way', 'relation']),
46490                 'modify': nest$$1(changes.modified.map(rep), ['node', 'way', 'relation']),
46491                 'delete': lodash.extend(nest$$1(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
46492             }
46493         };
46494     },
46495
46496
46497     changesetTags: function(version$$1, comment, imageryUsed) {
46498         var detected = utilDetect(),
46499             tags = {
46500                 created_by: ('iD ' + version$$1).substr(0, 255),
46501                 imagery_used: imageryUsed.join(';').substr(0, 255),
46502                 host: detected.host.substr(0, 255),
46503                 locale: detected.locale.substr(0, 255)
46504             };
46505
46506         if (comment) {
46507             tags.comment = comment.substr(0, 255);
46508         }
46509
46510         return tags;
46511     },
46512
46513
46514     putChangeset: function(changes, version$$1, comment, imageryUsed, callback) {
46515         var that = this;
46516         oauth.xhr({
46517                 method: 'PUT',
46518                 path: '/api/0.6/changeset/create',
46519                 options: { header: { 'Content-Type': 'text/xml' } },
46520                 content: JXON.stringify(that.changesetJXON(that.changesetTags(version$$1, comment, imageryUsed)))
46521             }, function(err, changeset_id) {
46522                 if (err) return callback(err);
46523                 oauth.xhr({
46524                     method: 'POST',
46525                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
46526                     options: { header: { 'Content-Type': 'text/xml' } },
46527                     content: JXON.stringify(that.osmChangeJXON(changeset_id, changes))
46528                 }, function(err) {
46529                     if (err) return callback(err);
46530                     // POST was successful, safe to call the callback.
46531                     // Still attempt to close changeset, but ignore response because #2667
46532                     // Add delay to allow for postgres replication #1646 #2678
46533                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
46534                     oauth.xhr({
46535                         method: 'PUT',
46536                         path: '/api/0.6/changeset/' + changeset_id + '/close',
46537                         options: { header: { 'Content-Type': 'text/xml' } }
46538                     }, function() { return true; });
46539                 });
46540             });
46541     },
46542
46543
46544     userDetails: function(callback) {
46545         if (userDetails) {
46546             callback(undefined, userDetails);
46547             return;
46548         }
46549
46550         function done(err, user_details) {
46551             if (err) return callback(err);
46552
46553             var u = user_details.getElementsByTagName('user')[0],
46554                 img = u.getElementsByTagName('img'),
46555                 image_url = '';
46556
46557             if (img && img[0] && img[0].getAttribute('href')) {
46558                 image_url = img[0].getAttribute('href');
46559             }
46560
46561             userDetails = {
46562                 display_name: u.attributes.display_name.value,
46563                 image_url: image_url,
46564                 id: u.attributes.id.value
46565             };
46566
46567             callback(undefined, userDetails);
46568         }
46569
46570         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
46571     },
46572
46573
46574     userChangesets: function(callback) {
46575         this.userDetails(function(err, user) {
46576             if (err) {
46577                 callback(err);
46578                 return;
46579             }
46580
46581             function done(err, changesets) {
46582                 if (err) {
46583                     callback(err);
46584                 } else {
46585                     callback(undefined, Array.prototype.map.call(changesets.getElementsByTagName('changeset'),
46586                         function (changeset) {
46587                             return { tags: getTags(changeset) };
46588                         }
46589                     ));
46590                 }
46591             }
46592
46593             oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
46594         });
46595     },
46596
46597
46598     status: function(callback) {
46599         function done(xml$$1) {
46600             // update blacklists
46601             var elements = xml$$1.getElementsByTagName('blacklist'),
46602                 regexes = [];
46603             for (var i = 0; i < elements.length; i++) {
46604                 var regex = elements[i].getAttribute('regex');  // needs unencode?
46605                 if (regex) {
46606                     regexes.push(regex);
46607                 }
46608             }
46609             if (regexes.length) {
46610                 blacklists = regexes;
46611             }
46612
46613
46614             if (rateLimitError) {
46615                 callback(rateLimitError, 'rateLimited');
46616             } else {
46617                 var apiStatus = xml$$1.getElementsByTagName('status'),
46618                     val = apiStatus[0].getAttribute('api');
46619
46620                 callback(undefined, val);
46621             }
46622         }
46623
46624         xml(urlroot + '/api/capabilities').get()
46625             .on('load', done)
46626             .on('error', callback);
46627     },
46628
46629
46630     imageryBlacklists: function() {
46631         return blacklists;
46632     },
46633
46634
46635     tileZoom: function(_) {
46636         if (!arguments.length) return tileZoom$1;
46637         tileZoom$1 = _;
46638         return this;
46639     },
46640
46641
46642     loadTiles: function(projection, dimensions, callback) {
46643         if (off) return;
46644
46645         var that = this,
46646             s = projection.scale() * 2 * Math.PI,
46647             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
46648             ts = 256 * Math.pow(2, z - tileZoom$1),
46649             origin = [
46650                 s / 2 - projection.translate()[0],
46651                 s / 2 - projection.translate()[1]
46652             ];
46653
46654         var tiles = d3geoTile()
46655             .scaleExtent([tileZoom$1, tileZoom$1])
46656             .scale(s)
46657             .size(dimensions)
46658             .translate(projection.translate())()
46659             .map(function(tile) {
46660                 var x = tile[0] * ts - origin[0],
46661                     y = tile[1] * ts - origin[1];
46662
46663                 return {
46664                     id: tile.toString(),
46665                     extent: geoExtent$$1(
46666                         projection.invert([x, y + ts]),
46667                         projection.invert([x + ts, y]))
46668                 };
46669             });
46670
46671         lodash.filter(inflight, function(v, i) {
46672             var wanted = lodash.find(tiles, function(tile) {
46673                 return i === tile.id;
46674             });
46675             if (!wanted) delete inflight[i];
46676             return !wanted;
46677         }).map(abortRequest$1);
46678
46679         tiles.forEach(function(tile) {
46680             var id = tile.id;
46681
46682             if (loadedTiles[id] || inflight[id]) return;
46683
46684             if (lodash.isEmpty(inflight)) {
46685                 dispatch$3.call('loading');
46686             }
46687
46688             inflight[id] = that.loadFromAPI(
46689                 '/api/0.6/map?bbox=' + tile.extent.toParam(),
46690                 function(err, parsed) {
46691                     delete inflight[id];
46692                     if (!err) {
46693                         loadedTiles[id] = true;
46694                     }
46695
46696                     if (callback) {
46697                         callback(err, lodash.extend({ data: parsed }, tile));
46698                     }
46699
46700                     if (lodash.isEmpty(inflight)) {
46701                         dispatch$3.call('loaded');
46702                     }
46703                 }
46704             );
46705         });
46706     },
46707
46708
46709     switch: function(options) {
46710         urlroot = options.urlroot;
46711
46712         oauth.options(lodash.extend({
46713             url: urlroot,
46714             loading: authLoading,
46715             done: authDone
46716         }, options));
46717         dispatch$3.call('change');
46718         this.reset();
46719         return this;
46720     },
46721
46722
46723     toggle: function(_) {
46724         off = !_;
46725         return this;
46726     },
46727
46728
46729     loadedTiles: function(_) {
46730         if (!arguments.length) return loadedTiles;
46731         loadedTiles = _;
46732         return this;
46733     },
46734
46735
46736     logout: function() {
46737         userDetails = undefined;
46738         oauth.logout();
46739         dispatch$3.call('change');
46740         return this;
46741     },
46742
46743
46744     authenticate: function(callback) {
46745         userDetails = undefined;
46746         function done(err, res) {
46747             rateLimitError = undefined;
46748             dispatch$3.call('change');
46749             if (callback) callback(err, res);
46750         }
46751         return oauth.authenticate(done);
46752     }
46753 };
46754
46755 var endpoint$1 = 'https://taginfo.openstreetmap.org/api/4/';
46756 var taginfoCache = {};
46757 var tag_sorts = {
46758         point: 'count_nodes',
46759         vertex: 'count_nodes',
46760         area: 'count_ways',
46761         line: 'count_ways'
46762     };
46763 var tag_sort_members = {
46764         point: 'count_node_members',
46765         vertex: 'count_node_members',
46766         area: 'count_way_members',
46767         line: 'count_way_members',
46768         relation: 'count_relation_members'
46769     };
46770 var tag_filters = {
46771         point: 'nodes',
46772         vertex: 'nodes',
46773         area: 'ways',
46774         line: 'ways'
46775     };
46776 var tag_members_fractions = {
46777         point: 'count_node_members_fraction',
46778         vertex: 'count_node_members_fraction',
46779         area: 'count_way_members_fraction',
46780         line: 'count_way_members_fraction',
46781         relation: 'count_relation_members_fraction'
46782     };
46783
46784
46785 function sets(parameters, n, o) {
46786     if (parameters.geometry && o[parameters.geometry]) {
46787         parameters[n] = o[parameters.geometry];
46788     }
46789     return parameters;
46790 }
46791
46792
46793 function setFilter(parameters) {
46794     return sets(parameters, 'filter', tag_filters);
46795 }
46796
46797
46798 function setSort(parameters) {
46799     return sets(parameters, 'sortname', tag_sorts);
46800 }
46801
46802
46803 function setSortMembers(parameters) {
46804     return sets(parameters, 'sortname', tag_sort_members);
46805 }
46806
46807
46808 function clean(parameters) {
46809     return lodash.omit(parameters, 'geometry', 'debounce');
46810 }
46811
46812
46813 function filterKeys(type) {
46814     var count_type = type ? 'count_' + type : 'count_all';
46815     return function(d) {
46816         return parseFloat(d[count_type]) > 2500 || d.in_wiki;
46817     };
46818 }
46819
46820
46821 function filterMultikeys(prefix) {
46822     return function(d) {
46823         // d.key begins with prefix, and d.key contains no additional ':'s
46824         var re = new RegExp('^' + prefix + '(.*)$');
46825         var matches = d.key.match(re) || [];
46826         return (matches.length === 2 && matches[1].indexOf(':') === -1);
46827     };
46828 }
46829
46830
46831 function filterValues(allowUpperCase) {
46832     return function(d) {
46833         if (d.value.match(/[;,]/) !== null) return false;  // exclude some punctuation
46834         if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false;  // exclude uppercase letters
46835         return parseFloat(d.fraction) > 0.0 || d.in_wiki;
46836     };
46837 }
46838
46839
46840 function filterRoles(geometry) {
46841     return function(d) {
46842         if (d.role === '') return false; // exclude empty role
46843         if (d.role.match(/[A-Z*;,]/) !== null) return false;  // exclude uppercase letters and some punctuation
46844         return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
46845     };
46846 }
46847
46848
46849 function valKey(d) {
46850     return {
46851         value: d.key,
46852         title: d.key
46853     };
46854 }
46855
46856
46857 function valKeyDescription(d) {
46858     return {
46859         value: d.value,
46860         title: d.description || d.value
46861     };
46862 }
46863
46864
46865 function roleKey(d) {
46866     return {
46867         value: d.role,
46868         title: d.role
46869     };
46870 }
46871
46872
46873 // sort keys with ':' lower than keys without ':'
46874 function sortKeys(a, b) {
46875     return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
46876         : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
46877         : 0;
46878 }
46879
46880
46881 var debounced = lodash.debounce(json, 100, true);
46882
46883
46884 function request$1(url, debounce, callback) {
46885     if (taginfoCache[url]) {
46886         callback(null, taginfoCache[url]);
46887     } else if (debounce) {
46888         debounced(url, done);
46889     } else {
46890         json(url, done);
46891     }
46892
46893     function done(err, data) {
46894         if (!err) {
46895             taginfoCache[url] = data;
46896         }
46897         callback(err, data);
46898     }
46899 }
46900
46901
46902 var serviceTaginfo = {
46903
46904     init: function() { taginfoCache = {}; },
46905     reset: function() { taginfoCache = {}; },
46906
46907
46908     keys: function(parameters, callback) {
46909         var debounce = parameters.debounce;
46910         parameters = clean(setSort(parameters));
46911         request$1(endpoint$1 + 'keys/all?' +
46912             utilQsString(lodash.extend({
46913                 rp: 10,
46914                 sortname: 'count_all',
46915                 sortorder: 'desc',
46916                 page: 1
46917             }, parameters)), debounce, function(err, d) {
46918                 if (err) {
46919                     callback(err);
46920                 } else {
46921                     var f = filterKeys(parameters.filter);
46922                     callback(null, d.data.filter(f).sort(sortKeys).map(valKey));
46923                 }
46924             }
46925         );
46926     },
46927
46928
46929     multikeys: function(parameters, callback) {
46930         var debounce = parameters.debounce;
46931         parameters = clean(setSort(parameters));
46932         var prefix = parameters.query;
46933         request$1(endpoint$1 + 'keys/all?' +
46934             utilQsString(lodash.extend({
46935                 rp: 25,
46936                 sortname: 'count_all',
46937                 sortorder: 'desc',
46938                 page: 1
46939             }, parameters)), debounce, function(err, d) {
46940                 if (err) {
46941                     callback(err);
46942                 } else {
46943                     var f = filterMultikeys(prefix);
46944                     callback(null, d.data.filter(f).map(valKey));
46945                 }
46946             }
46947         );
46948     },
46949
46950
46951     values: function(parameters, callback) {
46952         var debounce = parameters.debounce;
46953         parameters = clean(setSort(setFilter(parameters)));
46954         request$1(endpoint$1 + 'key/values?' +
46955             utilQsString(lodash.extend({
46956                 rp: 25,
46957                 sortname: 'count_all',
46958                 sortorder: 'desc',
46959                 page: 1
46960             }, parameters)), debounce, function(err, d) {
46961                 if (err) {
46962                     callback(err);
46963                 } else {
46964                     // In most cases we prefer taginfo value results with lowercase letters.
46965                     // A few OSM keys expect values to contain uppercase values (see #3377).
46966                     // This is not an exhaustive list (e.g. `name` also has uppercase values)
46967                     // but these are the fields where taginfo value lookup is most useful.
46968                     var re = /network|taxon|genus|species/;
46969                     var allowUpperCase = (parameters.key.match(re) !== null);
46970                     var f = filterValues(allowUpperCase);
46971                     callback(null, d.data.filter(f).map(valKeyDescription));
46972                 }
46973             }
46974         );
46975     },
46976
46977
46978     roles: function(parameters, callback) {
46979         var debounce = parameters.debounce;
46980         var geometry = parameters.geometry;
46981         parameters = clean(setSortMembers(parameters));
46982         request$1(endpoint$1 + 'relation/roles?' +
46983             utilQsString(lodash.extend({
46984                 rp: 25,
46985                 sortname: 'count_all_members',
46986                 sortorder: 'desc',
46987                 page: 1
46988             }, parameters)), debounce, function(err, d) {
46989                 if (err) {
46990                     callback(err);
46991                 } else {
46992                     var f = filterRoles(geometry);
46993                     callback(null, d.data.filter(f).map(roleKey));
46994                 }
46995             }
46996         );
46997     },
46998
46999
47000     docs: function(parameters, callback) {
47001         var debounce = parameters.debounce;
47002         parameters = clean(setSort(parameters));
47003
47004         var path$$1 = 'key/wiki_pages?';
47005         if (parameters.value) path$$1 = 'tag/wiki_pages?';
47006         else if (parameters.rtype) path$$1 = 'relation/wiki_pages?';
47007
47008         request$1(endpoint$1 + path$$1 + utilQsString(parameters), debounce, function(err, d) {
47009             if (err) {
47010                 callback(err);
47011             } else {
47012                 callback(null, d.data);
47013             }
47014         });
47015     },
47016
47017
47018     endpoint: function(_) {
47019         if (!arguments.length) return endpoint$1;
47020         endpoint$1 = _;
47021         return this;
47022     }
47023
47024 };
47025
47026 var jsonpCache = {};
47027 window.jsonpCache = jsonpCache;
47028
47029 function jsonpRequest(url, callback) {
47030
47031   if (window.JSONP_FIX) {
47032     if (window.JSONP_DELAY === 0) {
47033       callback(window.JSONP_FIX);
47034     } else {
47035       setTimeout(function() {
47036         callback(window.JSONP_FIX);
47037       }, window.JSONP_DELAY || 0);
47038     }
47039     return;
47040   }
47041
47042   function rand() {
47043     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
47044       c = '', i = -1;
47045     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
47046     return c;
47047   }
47048
47049   function create(url) {
47050     var e = url.match(/callback=(\w+)/),
47051       c = e ? e[1] : rand();
47052     jsonpCache[c] = function(data) {
47053       callback(data);
47054       delete jsonpCache[c];
47055       script.remove();
47056     };
47057     return 'jsonpCache.' + c;
47058   }
47059
47060   var cb = create(url),
47061     script = select('head')
47062     .append('script')
47063     .attr('type', 'text/javascript')
47064     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
47065 }
47066
47067 var endpoint$2 = 'https://www.wikidata.org/w/api.php?';
47068
47069 var serviceWikidata = {
47070
47071     init: function() {},
47072     reset: function() {},
47073
47074
47075     // Given a Wikipedia language and article title, return an array of
47076     // corresponding Wikidata entities.
47077     itemsByTitle: function(lang, title, callback) {
47078         if (!title) {
47079             callback('', {});
47080             return;
47081         }
47082
47083         lang = lang || 'en';
47084         jsonpRequest(endpoint$2 + utilQsString({
47085             action: 'wbgetentities',
47086             format: 'json',
47087             sites: lang.replace(/-/g, '_') + 'wiki',
47088             titles: title,
47089             languages: 'en', // shrink response by filtering to one language
47090             callback: '{callback}'
47091         }), function(data) {
47092             if (!data || data.error) {
47093                 callback('', {});
47094             } else {
47095                 callback(title, data.entities || {});
47096             }
47097         });
47098     }
47099
47100 };
47101
47102 var endpoint$3 = 'https://en.wikipedia.org/w/api.php?';
47103
47104 var serviceWikipedia = {
47105
47106     init: function() {},
47107     reset: function() {},
47108
47109
47110     search: function(lang, query, callback) {
47111         if (!query) {
47112             callback('', []);
47113             return;
47114         }
47115
47116         lang = lang || 'en';
47117         jsonpRequest(endpoint$3.replace('en', lang) +
47118             utilQsString({
47119                 action: 'query',
47120                 list: 'search',
47121                 srlimit: '10',
47122                 srinfo: 'suggestion',
47123                 format: 'json',
47124                 callback: '{callback}',
47125                 srsearch: query
47126             }), function(data) {
47127                 if (!data || !data.query || !data.query.search || data.error) {
47128                     callback('', []);
47129                 } else {
47130                     var results = data.query.search.map(function(d) { return d.title; });
47131                     callback(query, results);
47132                 }
47133             }
47134         );
47135     },
47136
47137
47138     suggestions: function(lang, query, callback) {
47139         if (!query) {
47140             callback('', []);
47141             return;
47142         }
47143
47144         lang = lang || 'en';
47145         jsonpRequest(endpoint$3.replace('en', lang) +
47146             utilQsString({
47147                 action: 'opensearch',
47148                 namespace: 0,
47149                 suggest: '',
47150                 format: 'json',
47151                 callback: '{callback}',
47152                 search: query
47153             }), function(data) {
47154                 if (!data || data.error) {
47155                     callback('', []);
47156                 } else {
47157                     callback(data[0], data[1] || []);
47158                 }
47159             }
47160         );
47161     },
47162
47163
47164     translations: function(lang, title, callback) {
47165         if (!title) {
47166             callback({});
47167             return;
47168         }
47169
47170         jsonpRequest(endpoint$3.replace('en', lang) +
47171             utilQsString({
47172                 action: 'query',
47173                 prop: 'langlinks',
47174                 format: 'json',
47175                 callback: '{callback}',
47176                 lllimit: 500,
47177                 titles: title
47178             }), function(data) {
47179                 if (!data || !data.query || !data.query.pages || data.error) {
47180                     callback({});
47181                 } else {
47182                     var list = data.query.pages[Object.keys(data.query.pages)[0]],
47183                         translations = {};
47184                     if (list && list.langlinks) {
47185                         list.langlinks.forEach(function(d) {
47186                             translations[d.lang] = d['*'];
47187                         });
47188                     }
47189                     callback(translations);
47190                 }
47191             }
47192         );
47193     }
47194
47195 };
47196
47197 var services = {
47198     mapillary: serviceMapillary,
47199     nominatim: serviceNominatim,
47200     osm: serviceOsm,
47201     taginfo: serviceTaginfo,
47202     wikidata: serviceWikidata,
47203     wikipedia: serviceWikipedia
47204 };
47205
47206 function svgMapillaryImages(projection, context, dispatch$$1) {
47207     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47208         minZoom = 12,
47209         minViewfieldZoom = 17,
47210         layer = select(null),
47211         _mapillary;
47212
47213
47214     function init() {
47215         if (svgMapillaryImages.initialized) return;  // run once
47216         svgMapillaryImages.enabled = false;
47217         svgMapillaryImages.initialized = true;
47218     }
47219
47220
47221     function getMapillary() {
47222         if (services.mapillary && !_mapillary) {
47223             _mapillary = services.mapillary;
47224             _mapillary.event.on('loadedImages', throttledRedraw);
47225         } else if (!services.mapillary && _mapillary) {
47226             _mapillary = null;
47227         }
47228
47229         return _mapillary;
47230     }
47231
47232
47233     function showLayer() {
47234         var mapillary = getMapillary();
47235         if (!mapillary) return;
47236
47237         mapillary.loadViewer(context);
47238         editOn();
47239
47240         layer
47241             .style('opacity', 0)
47242             .transition()
47243             .duration(500)
47244             .style('opacity', 1)
47245             .on('end', function () { dispatch$$1.call('change'); });
47246     }
47247
47248
47249     function hideLayer() {
47250         var mapillary = getMapillary();
47251         if (mapillary) {
47252             mapillary.hideViewer();
47253         }
47254
47255         throttledRedraw.cancel();
47256
47257         layer
47258             .transition()
47259             .duration(500)
47260             .style('opacity', 0)
47261             .on('end', editOff);
47262     }
47263
47264
47265     function editOn() {
47266         layer.style('display', 'block');
47267     }
47268
47269
47270     function editOff() {
47271         layer.selectAll('.viewfield-group').remove();
47272         layer.style('display', 'none');
47273     }
47274
47275
47276     function click(d) {
47277         var mapillary = getMapillary();
47278         if (!mapillary) return;
47279
47280         context.map().centerEase(d.loc);
47281
47282         mapillary
47283             .selectedImage(d.key, true)
47284             .updateViewer(d.key, context)
47285             .showViewer();
47286     }
47287
47288
47289     function transform(d) {
47290         var t = svgPointTransform(projection)(d);
47291         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
47292         return t;
47293     }
47294
47295
47296     function update() {
47297         var mapillary = getMapillary(),
47298             data = (mapillary ? mapillary.images(projection) : []),
47299             imageKey = mapillary ? mapillary.selectedImage() : null;
47300
47301         var markers = layer.selectAll('.viewfield-group')
47302             .data(data, function(d) { return d.key; });
47303
47304         markers.exit()
47305             .remove();
47306
47307         var enter = markers.enter()
47308             .append('g')
47309             .attr('class', 'viewfield-group')
47310             .classed('selected', function(d) { return d.key === imageKey; })
47311             .on('click', click);
47312
47313         markers = markers
47314             .merge(enter)
47315             .attr('transform', transform);
47316
47317
47318        var viewfields = markers.selectAll('.viewfield')
47319             .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
47320
47321         viewfields.exit()
47322             .remove();
47323
47324         viewfields.enter()
47325             .append('path')
47326             .attr('class', 'viewfield')
47327             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
47328             .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');
47329
47330         markers.selectAll('circle')
47331             .data([0])
47332             .enter()
47333             .append('circle')
47334             .attr('dx', '0')
47335             .attr('dy', '0')
47336             .attr('r', '6');
47337     }
47338
47339
47340     function drawImages(selection$$1) {
47341         var enabled = svgMapillaryImages.enabled,
47342             mapillary = getMapillary();
47343
47344         layer = selection$$1.selectAll('.layer-mapillary-images')
47345             .data(mapillary ? [0] : []);
47346
47347         layer.exit()
47348             .remove();
47349
47350         layer = layer.enter()
47351             .append('g')
47352             .attr('class', 'layer-mapillary-images')
47353             .style('display', enabled ? 'block' : 'none')
47354             .merge(layer);
47355
47356         if (enabled) {
47357             if (mapillary && ~~context.map().zoom() >= minZoom) {
47358                 editOn();
47359                 update();
47360                 mapillary.loadImages(projection);
47361             } else {
47362                 editOff();
47363             }
47364         }
47365     }
47366
47367
47368     drawImages.enabled = function(_) {
47369         if (!arguments.length) return svgMapillaryImages.enabled;
47370         svgMapillaryImages.enabled = _;
47371         if (svgMapillaryImages.enabled) {
47372             showLayer();
47373         } else {
47374             hideLayer();
47375         }
47376         dispatch$$1.call('change');
47377         return this;
47378     };
47379
47380
47381     drawImages.supported = function() {
47382         return !!getMapillary();
47383     };
47384
47385
47386     init();
47387     return drawImages;
47388 }
47389
47390 function svgMapillarySigns(projection, context, dispatch$$1) {
47391     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47392         minZoom = 12,
47393         layer = select(null),
47394         _mapillary;
47395
47396
47397     function init() {
47398         if (svgMapillarySigns.initialized) return;  // run once
47399         svgMapillarySigns.enabled = false;
47400         svgMapillarySigns.initialized = true;
47401     }
47402
47403
47404     function getMapillary() {
47405         if (services.mapillary && !_mapillary) {
47406             _mapillary = services.mapillary;
47407             _mapillary.event.on('loadedSigns', throttledRedraw);
47408         } else if (!services.mapillary && _mapillary) {
47409             _mapillary = null;
47410         }
47411         return _mapillary;
47412     }
47413
47414
47415     function showLayer() {
47416         editOn();
47417     }
47418
47419
47420     function hideLayer() {
47421         throttledRedraw.cancel();
47422         editOff();
47423     }
47424
47425
47426     function editOn() {
47427         layer.style('display', 'block');
47428     }
47429
47430
47431     function editOff() {
47432         layer.selectAll('.icon-sign').remove();
47433         layer.style('display', 'none');
47434     }
47435
47436
47437     function click(d) {
47438         var mapillary = getMapillary();
47439         if (!mapillary) return;
47440
47441         context.map().centerEase(d.loc);
47442
47443         mapillary
47444             .selectedImage(d.key, true)
47445             .updateViewer(d.key, context)
47446             .showViewer();
47447     }
47448
47449
47450     function update() {
47451         var mapillary = getMapillary(),
47452             data = (mapillary ? mapillary.signs(projection) : []),
47453             imageKey = mapillary ? mapillary.selectedImage() : null;
47454
47455         var signs = layer.selectAll('.icon-sign')
47456             .data(data, function(d) { return d.key; });
47457
47458         signs.exit()
47459             .remove();
47460
47461         var enter = signs.enter()
47462             .append('foreignObject')
47463             .attr('class', 'icon-sign')
47464             .attr('width', '32px')      // for Firefox
47465             .attr('height', '32px')     // for Firefox
47466             .classed('selected', function(d) { return d.key === imageKey; })
47467             .on('click', click);
47468
47469         enter
47470             .append('xhtml:body')
47471             .attr('class', 'icon-sign-body')
47472             .html(mapillary.signHTML);
47473
47474         signs
47475             .merge(enter)
47476             .attr('x', function(d) { return projection(d.loc)[0] - 16; })   // offset by -16px to
47477             .attr('y', function(d) { return projection(d.loc)[1] - 16; });  // center signs on loc
47478     }
47479
47480
47481     function drawSigns(selection$$1) {
47482         var enabled = svgMapillarySigns.enabled,
47483             mapillary = getMapillary();
47484
47485         layer = selection$$1.selectAll('.layer-mapillary-signs')
47486             .data(mapillary ? [0] : []);
47487
47488         layer.exit()
47489             .remove();
47490
47491         layer = layer.enter()
47492             .append('g')
47493             .attr('class', 'layer-mapillary-signs')
47494             .style('display', enabled ? 'block' : 'none')
47495             .merge(layer);
47496
47497         if (enabled) {
47498             if (mapillary && ~~context.map().zoom() >= minZoom) {
47499                 editOn();
47500                 update();
47501                 mapillary.loadSigns(context, projection);
47502             } else {
47503                 editOff();
47504             }
47505         }
47506     }
47507
47508
47509     drawSigns.enabled = function(_) {
47510         if (!arguments.length) return svgMapillarySigns.enabled;
47511         svgMapillarySigns.enabled = _;
47512         if (svgMapillarySigns.enabled) {
47513             showLayer();
47514         } else {
47515             hideLayer();
47516         }
47517         dispatch$$1.call('change');
47518         return this;
47519     };
47520
47521
47522     drawSigns.supported = function() {
47523         var mapillary = getMapillary();
47524         return (mapillary && mapillary.signsSupported());
47525     };
47526
47527
47528     init();
47529     return drawSigns;
47530 }
47531
47532 function svgOsm() {
47533     return function drawOsm(selection) {
47534         var layers = selection.selectAll('.layer-osm')
47535             .data(['areas', 'lines', 'hit', 'halo', 'label']);
47536
47537         layers.enter()
47538             .append('g')
47539             .attr('class', function(d) { return 'layer-osm layer-' + d; });
47540     };
47541 }
47542
47543 function svgLayers(projection, context) {
47544     var dispatch$$1 = dispatch('change'),
47545         svg = select(null),
47546         layers = [
47547             { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
47548             { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
47549             { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
47550             { id: 'mapillary-signs',  layer: svgMapillarySigns(projection, context, dispatch$$1) },
47551             { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
47552         ];
47553
47554
47555     function drawLayers(selection$$1) {
47556         svg = selection$$1.selectAll('.surface')
47557             .data([0]);
47558
47559         svg = svg.enter()
47560             .append('svg')
47561             .attr('class', 'surface')
47562             .merge(svg);
47563
47564         var defs = svg.selectAll('.surface-defs')
47565             .data([0]);
47566
47567         defs.enter()
47568             .append('defs')
47569             .attr('class', 'surface-defs');
47570
47571         var groups = svg.selectAll('.data-layer')
47572             .data(layers);
47573
47574         groups.exit()
47575             .remove();
47576
47577         groups.enter()
47578             .append('g')
47579             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
47580             .merge(groups)
47581             .each(function(d) { select(this).call(d.layer); });
47582     }
47583
47584
47585     drawLayers.all = function() {
47586         return layers;
47587     };
47588
47589
47590     drawLayers.layer = function(id) {
47591         var obj = lodash.find(layers, function(o) {return o.id === id;});
47592         return obj && obj.layer;
47593     };
47594
47595
47596     drawLayers.only = function(what) {
47597         var arr = [].concat(what);
47598         drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
47599         return this;
47600     };
47601
47602
47603     drawLayers.remove = function(what) {
47604         var arr = [].concat(what);
47605         arr.forEach(function(id) {
47606             layers = lodash.reject(layers, function(o) {return o.id === id;});
47607         });
47608         dispatch$$1.call('change');
47609         return this;
47610     };
47611
47612
47613     drawLayers.add = function(what) {
47614         var arr = [].concat(what);
47615         arr.forEach(function(obj) {
47616             if ('id' in obj && 'layer' in obj) {
47617                 layers.push(obj);
47618             }
47619         });
47620         dispatch$$1.call('change');
47621         return this;
47622     };
47623
47624
47625     drawLayers.dimensions = function(_) {
47626         if (!arguments.length) return utilGetDimensions(svg);
47627         utilSetDimensions(svg, _);
47628         return this;
47629     };
47630
47631
47632     return utilRebind(drawLayers, dispatch$$1, 'on');
47633 }
47634
47635 function svgLines$$1(projection) {
47636     var detected = utilDetect();
47637
47638     var highway_stack = {
47639         motorway: 0,
47640         motorway_link: 1,
47641         trunk: 2,
47642         trunk_link: 3,
47643         primary: 4,
47644         primary_link: 5,
47645         secondary: 6,
47646         tertiary: 7,
47647         unclassified: 8,
47648         residential: 9,
47649         service: 10,
47650         footway: 11
47651     };
47652
47653     function waystack(a, b) {
47654         var as = 0, bs = 0;
47655         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
47656         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
47657         return as - bs;
47658     }
47659
47660
47661     return function drawLines(selection$$1, graph, entities, filter) {
47662         var ways = [], pathdata = {}, onewaydata = {},
47663             getPath = svgPath(projection, graph);
47664
47665         for (var i = 0; i < entities.length; i++) {
47666             var entity = entities[i],
47667                 outer = osmSimpleMultipolygonOuterMember(entity, graph);
47668             if (outer) {
47669                 ways.push(entity.mergeTags(outer.tags));
47670             } else if (entity.geometry(graph) === 'line') {
47671                 ways.push(entity);
47672             }
47673         }
47674
47675         ways = ways.filter(getPath);
47676
47677         pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
47678
47679         lodash.forOwn(pathdata, function(v, k) {
47680             onewaydata[k] = lodash(v)
47681                 .filter(function(d) { return d.isOneWay(); })
47682                 .map(svgOneWaySegments(projection, graph, 35))
47683                 .flatten()
47684                 .valueOf();
47685         });
47686
47687         var layer = selection$$1.selectAll('.layer-lines');
47688
47689         var layergroup = layer
47690             .selectAll('g.layergroup')
47691             .data(range(-10, 11));
47692
47693         layergroup = layergroup.enter()
47694             .append('g')
47695             .attr('class', function(d) { return 'layergroup layer' + String(d); })
47696             .merge(layergroup);
47697
47698
47699         var linegroup = layergroup
47700             .selectAll('g.linegroup')
47701             .data(['shadow', 'casing', 'stroke']);
47702
47703         linegroup = linegroup.enter()
47704             .append('g')
47705             .attr('class', function(d) { return 'linegroup line-' + d; })
47706             .merge(linegroup);
47707
47708
47709         var lines = linegroup
47710             .selectAll('path')
47711             .filter(filter)
47712             .data(
47713                 function() { return pathdata[this.parentNode.__data__] || []; },
47714                 osmEntity$$1.key
47715             );
47716
47717         lines.exit()
47718             .remove();
47719
47720         // Optimization: call simple TagClasses only on enter selection. This
47721         // works because osmEntity.key is defined to include the entity v attribute.
47722         lines.enter()
47723             .append('path')
47724             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
47725             .call(svgTagClasses())
47726             .merge(lines)
47727                 .sort(waystack)
47728                 .attr('d', getPath)
47729                 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
47730
47731
47732         var onewaygroup = layergroup
47733             .selectAll('g.onewaygroup')
47734             .data(['oneway']);
47735
47736         onewaygroup = onewaygroup.enter()
47737             .append('g')
47738             .attr('class', 'onewaygroup')
47739             .merge(onewaygroup);
47740
47741
47742         var oneways = onewaygroup
47743             .selectAll('path')
47744             .filter(filter)
47745             .data(
47746                 function() { return onewaydata[this.parentNode.__data__] || []; },
47747                 function(d) { return [d.id, d.index]; }
47748             );
47749
47750         oneways.exit()
47751             .remove();
47752
47753         oneways = oneways.enter()
47754             .append('path')
47755             .attr('class', 'oneway')
47756             .attr('marker-mid', 'url(#oneway-marker)')
47757             .merge(oneways)
47758             .attr('d', function(d) { return d.d; });
47759
47760         if (detected.ie) {
47761             oneways.each(function() { this.parentNode.insertBefore(this, this); });
47762         }
47763     };
47764 }
47765
47766 function svgMidpoints$$1(projection, context) {
47767
47768     return function drawMidpoints(selection, graph, entities, filter, extent) {
47769         var poly = extent.polygon(),
47770             midpoints = {};
47771
47772         for (var i = 0; i < entities.length; i++) {
47773             var entity = entities[i];
47774
47775             if (entity.type !== 'way')
47776                 continue;
47777             if (!filter(entity))
47778                 continue;
47779             if (context.selectedIDs().indexOf(entity.id) < 0)
47780                 continue;
47781
47782             var nodes = graph.childNodes(entity);
47783             for (var j = 0; j < nodes.length - 1; j++) {
47784
47785                 var a = nodes[j],
47786                     b = nodes[j + 1],
47787                     id = [a.id, b.id].sort().join('-');
47788
47789                 if (midpoints[id]) {
47790                     midpoints[id].parents.push(entity);
47791                 } else {
47792                     if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
47793                         var point = geoInterp(a.loc, b.loc, 0.5),
47794                             loc = null;
47795
47796                         if (extent.intersects(point)) {
47797                             loc = point;
47798                         } else {
47799                             for (var k = 0; k < 4; k++) {
47800                                 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
47801                                 if (point &&
47802                                     geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
47803                                     geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
47804                                 {
47805                                     loc = point;
47806                                     break;
47807                                 }
47808                             }
47809                         }
47810
47811                         if (loc) {
47812                             midpoints[id] = {
47813                                 type: 'midpoint',
47814                                 id: id,
47815                                 loc: loc,
47816                                 edge: [a.id, b.id],
47817                                 parents: [entity]
47818                             };
47819                         }
47820                     }
47821                 }
47822             }
47823         }
47824
47825
47826         function midpointFilter(d) {
47827             if (midpoints[d.id])
47828                 return true;
47829
47830             for (var i = 0; i < d.parents.length; i++) {
47831                 if (filter(d.parents[i])) {
47832                     return true;
47833                 }
47834             }
47835
47836             return false;
47837         }
47838
47839
47840         var layer = selection.selectAll('.layer-hit');
47841
47842         var groups = layer
47843             .selectAll('g.midpoint')
47844             .filter(midpointFilter)
47845             .data(lodash.values(midpoints), function(d) { return d.id; });
47846
47847         groups.exit()
47848             .remove();
47849
47850         var enter = groups.enter()
47851             .insert('g', ':first-child')
47852             .attr('class', 'midpoint');
47853
47854         enter.append('polygon')
47855             .attr('points', '-6,8 10,0 -6,-8')
47856             .attr('class', 'shadow');
47857
47858         enter.append('polygon')
47859             .attr('points', '-3,4 5,0 -3,-4')
47860             .attr('class', 'fill');
47861
47862         groups = groups
47863             .merge(enter)
47864             .attr('transform', function(d) {
47865                 var translate = svgPointTransform(projection),
47866                     a = graph.entity(d.edge[0]),
47867                     b = graph.entity(d.edge[1]),
47868                     angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
47869                 return translate(d) + ' rotate(' + angleVal + ')';
47870             })
47871             .call(svgTagClasses().tags(
47872                 function(d) { return d.parents[0].tags; }
47873             ));
47874
47875         // Propagate data bindings.
47876         groups.select('polygon.shadow');
47877         groups.select('polygon.fill');
47878
47879     };
47880 }
47881
47882 function svgOneWaySegments(projection, graph, dt) {
47883     return function(entity) {
47884         var a,
47885             b,
47886             i = 0,
47887             offset = dt,
47888             segments = [],
47889             clip = identity$8().clipExtent(projection.clipExtent()).stream,
47890             coordinates = graph.childNodes(entity).map(function(n) {
47891                 return n.loc;
47892             });
47893
47894         if (entity.tags.oneway === '-1') coordinates.reverse();
47895
47896         geoStream({
47897             type: 'LineString',
47898             coordinates: coordinates
47899         }, projection.stream(clip({
47900             lineStart: function() {},
47901             lineEnd: function() {
47902                 a = null;
47903             },
47904             point: function(x, y) {
47905                 b = [x, y];
47906
47907                 if (a) {
47908                     var span = geoEuclideanDistance(a, b) - offset;
47909
47910                     if (span >= 0) {
47911                         var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
47912                             dx = dt * Math.cos(angle),
47913                             dy = dt * Math.sin(angle),
47914                             p = [a[0] + offset * Math.cos(angle),
47915                                  a[1] + offset * Math.sin(angle)];
47916
47917                         var segment = 'M' + a[0] + ',' + a[1] +
47918                                       'L' + p[0] + ',' + p[1];
47919
47920                         for (span -= dt; span >= 0; span -= dt) {
47921                             p[0] += dx;
47922                             p[1] += dy;
47923                             segment += 'L' + p[0] + ',' + p[1];
47924                         }
47925
47926                         segment += 'L' + b[0] + ',' + b[1];
47927                         segments.push({id: entity.id, index: i, d: segment});
47928                     }
47929
47930                     offset = -span;
47931                     i++;
47932                 }
47933
47934                 a = b;
47935             }
47936         })));
47937
47938         return segments;
47939     };
47940 }
47941
47942 function svgPath(projection, graph, isArea) {
47943
47944     // Explanation of magic numbers:
47945     // "padding" here allows space for strokes to extend beyond the viewport,
47946     // so that the stroke isn't drawn along the edge of the viewport when
47947     // the shape is clipped.
47948     //
47949     // When drawing lines, pad viewport by 5px.
47950     // When drawing areas, pad viewport by 65px in each direction to allow
47951     // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
47952
47953     var cache = {},
47954         padding = isArea ? 65 : 5,
47955         viewport = projection.clipExtent(),
47956         paddedExtent = [
47957             [viewport[0][0] - padding, viewport[0][1] - padding],
47958             [viewport[1][0] + padding, viewport[1][1] + padding]
47959         ],
47960         clip = identity$8().clipExtent(paddedExtent).stream,
47961         project = projection.stream,
47962         path$$1 = index$5()
47963             .projection({stream: function(output) { return project(clip(output)); }});
47964
47965     return function(entity) {
47966         if (entity.id in cache) {
47967             return cache[entity.id];
47968         } else {
47969             return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
47970         }
47971     };
47972 }
47973
47974 function svgPoints$$1(projection, context) {
47975
47976     function markerPath(selection, klass) {
47977         selection
47978             .attr('class', klass)
47979             .attr('transform', 'translate(-8, -23)')
47980             .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');
47981     }
47982
47983     function sortY(a, b) {
47984         return b.loc[1] - a.loc[1];
47985     }
47986
47987
47988     return function drawPoints(selection, graph, entities, filter) {
47989         var wireframe = context.surface().classed('fill-wireframe'),
47990             points = wireframe ? [] : lodash.filter(entities, function(e) {
47991                 return e.geometry(graph) === 'point';
47992             });
47993
47994         points.sort(sortY);
47995
47996         var layer = selection.selectAll('.layer-hit');
47997
47998         var groups = layer.selectAll('g.point')
47999             .filter(filter)
48000             .data(points, osmEntity$$1.key);
48001
48002         groups.exit()
48003             .remove();
48004
48005         var enter = groups.enter()
48006             .append('g')
48007             .attr('class', function(d) { return 'node point ' + d.id; })
48008             .order();
48009
48010         enter.append('path')
48011             .call(markerPath, 'shadow');
48012
48013         enter.append('path')
48014             .call(markerPath, 'stroke');
48015
48016         enter.append('use')
48017             .attr('transform', 'translate(-6, -20)')
48018             .attr('class', 'icon')
48019             .attr('width', '12px')
48020             .attr('height', '12px');
48021
48022         groups = groups
48023             .merge(enter)
48024             .attr('transform', svgPointTransform(projection))
48025             .call(svgTagClasses());
48026
48027         // Selecting the following implicitly
48028         // sets the data (point entity) on the element
48029         groups.select('.shadow');
48030         groups.select('.stroke');
48031         groups.select('.icon')
48032             .attr('xlink:href', function(entity) {
48033                 var preset = context.presets().match(entity, graph);
48034                 return (preset && preset.icon) ? '#' + preset.icon + '-12' : '';
48035             });
48036     };
48037 }
48038
48039 function svgRelationMemberTags(graph) {
48040     return function(entity) {
48041         var tags = entity.tags;
48042         graph.parentRelations(entity).forEach(function(relation) {
48043             var type = relation.tags.type;
48044             if (type === 'multipolygon' || type === 'boundary') {
48045                 tags = lodash.extend({}, relation.tags, tags);
48046             }
48047         });
48048         return tags;
48049     };
48050 }
48051
48052 function svgTagClasses() {
48053     var primaries = [
48054             'building', 'highway', 'railway', 'waterway', 'aeroway',
48055             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
48056             'leisure', 'place'
48057         ],
48058         statuses = [
48059             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
48060             'razed', 'demolished', 'obliterated'
48061         ],
48062         secondaries = [
48063             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
48064             'surface', 'tracktype', 'crossing'
48065         ],
48066         tagClassRe = /^tag-/,
48067         tags = function(entity) { return entity.tags; };
48068
48069
48070     var tagClasses = function(selection$$1) {
48071         selection$$1.each(function tagClassesEach(entity) {
48072             var value = this.className,
48073                 classes, primary, status;
48074
48075             if (value.baseVal !== undefined) value = value.baseVal;
48076
48077             classes = value.trim().split(/\s+/).filter(function(name) {
48078                 return name.length && !tagClassRe.test(name);
48079             }).join(' ');
48080
48081             var t = tags(entity), i, k, v;
48082
48083             // pick at most one primary classification tag..
48084             for (i = 0; i < primaries.length; i++) {
48085                 k = primaries[i];
48086                 v = t[k];
48087                 if (!v || v === 'no') continue;
48088
48089                 primary = k;
48090                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
48091                     status = v;
48092                     classes += ' tag-' + k;
48093                 } else {
48094                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
48095                 }
48096
48097                 break;
48098             }
48099
48100             // add at most one status tag, only if relates to primary tag..
48101             if (!status) {
48102                 for (i = 0; i < statuses.length; i++) {
48103                     k = statuses[i];
48104                     v = t[k];
48105                     if (!v || v === 'no') continue;
48106
48107                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
48108                         status = k;
48109                     }
48110                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
48111                         status = k;
48112                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
48113                         status = k;
48114                         primary = v;
48115                         classes += ' tag-' + v;
48116                     }  // else ignore e.g.  `highway=path + abandoned=railway`
48117
48118                     if (status) break;
48119                 }
48120             }
48121
48122             if (status) {
48123                 classes += ' tag-status tag-status-' + status;
48124             }
48125
48126             // add any secondary (structure) tags
48127             for (i = 0; i < secondaries.length; i++) {
48128                 k = secondaries[i];
48129                 v = t[k];
48130                 if (!v || v === 'no') continue;
48131                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48132             }
48133
48134             // For highways, look for surface tagging..
48135             if (primary === 'highway') {
48136                 var paved = (t.highway !== 'track');
48137                 for (k in t) {
48138                     v = t[k];
48139                     if (k in osmPavedTags) {
48140                         paved = !!osmPavedTags[k][v];
48141                         break;
48142                     }
48143                 }
48144                 if (!paved) {
48145                     classes += ' tag-unpaved';
48146                 }
48147             }
48148
48149             classes = classes.trim();
48150
48151             if (classes !== value) {
48152                 select(this).attr('class', classes);
48153             }
48154         });
48155     };
48156
48157
48158     tagClasses.tags = function(_) {
48159         if (!arguments.length) return tags;
48160         tags = _;
48161         return tagClasses;
48162     };
48163
48164     return tagClasses;
48165 }
48166
48167 function svgTurns(projection) {
48168
48169     return function drawTurns(selection, graph, turns) {
48170
48171         function key(turn) {
48172             return [turn.from.node + turn.via.node + turn.to.node].join('-');
48173         }
48174
48175         function icon(turn) {
48176             var u = turn.u ? '-u' : '';
48177             if (!turn.restriction)
48178                 return '#turn-yes' + u;
48179             var restriction = graph.entity(turn.restriction).tags.restriction;
48180             return '#turn-' +
48181                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48182         }
48183
48184         var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48185             .data(turns, key);
48186
48187         groups.exit()
48188             .remove();
48189
48190
48191         var enter = groups.enter()
48192             .append('g')
48193             .attr('class', 'turn');
48194
48195         var nEnter = enter
48196             .filter(function (turn) { return !turn.u; });
48197
48198         nEnter.append('rect')
48199             .attr('transform', 'translate(-22, -12)')
48200             .attr('width', '44')
48201             .attr('height', '24');
48202
48203         nEnter.append('use')
48204             .attr('transform', 'translate(-22, -12)')
48205             .attr('width', '44')
48206             .attr('height', '24');
48207
48208
48209         var uEnter = enter
48210             .filter(function (turn) { return turn.u; });
48211
48212         uEnter.append('circle')
48213             .attr('r', '16');
48214
48215         uEnter.append('use')
48216             .attr('transform', 'translate(-16, -16)')
48217             .attr('width', '32')
48218             .attr('height', '32');
48219
48220
48221         groups = groups
48222             .merge(enter);
48223
48224         groups
48225             .attr('transform', function (turn) {
48226                 var v = graph.entity(turn.via.node),
48227                     t = graph.entity(turn.to.node),
48228                     a = geoAngle(v, t, projection),
48229                     p = projection(v.loc),
48230                     r = turn.u ? 0 : 60;
48231
48232                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
48233                     'rotate(' + a * 180 / Math.PI + ')';
48234             });
48235
48236         groups.select('use')
48237             .attr('xlink:href', icon);
48238
48239         groups.select('rect');
48240         groups.select('circle');
48241
48242         return this;
48243     };
48244 }
48245
48246 function svgVertices$$1(projection, context) {
48247     var radiuses = {
48248         //       z16-, z17, z18+, tagged
48249         shadow: [6,    7.5,   7.5,  11.5],
48250         stroke: [2.5,  3.5,   3.5,  7],
48251         fill:   [1,    1.5,   1.5,  1.5]
48252     };
48253
48254     var hover;
48255
48256     function siblingAndChildVertices(ids, graph, extent$$1) {
48257         var vertices = {};
48258
48259         function addChildVertices(entity) {
48260             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
48261                 var i;
48262                 if (entity.type === 'way') {
48263                     for (i = 0; i < entity.nodes.length; i++) {
48264                         addChildVertices(graph.entity(entity.nodes[i]));
48265                     }
48266                 } else if (entity.type === 'relation') {
48267                     for (i = 0; i < entity.members.length; i++) {
48268                         var member = context.hasEntity(entity.members[i].id);
48269                         if (member) {
48270                             addChildVertices(member);
48271                         }
48272                     }
48273                 } else if (entity.intersects(extent$$1, graph)) {
48274                     vertices[entity.id] = entity;
48275                 }
48276             }
48277         }
48278
48279         ids.forEach(function(id) {
48280             var entity = context.hasEntity(id);
48281             if (entity && entity.type === 'node') {
48282                 vertices[entity.id] = entity;
48283                 context.graph().parentWays(entity).forEach(function(entity) {
48284                     addChildVertices(entity);
48285                 });
48286             } else if (entity) {
48287                 addChildVertices(entity);
48288             }
48289         });
48290
48291         return vertices;
48292     }
48293
48294
48295     function draw(selection$$1, vertices, klass, graph, zoom$$1) {
48296
48297         function icon(entity) {
48298             if (entity.id in icons) return icons[entity.id];
48299             icons[entity.id] =
48300                 entity.hasInterestingTags() &&
48301                 context.presets().match(entity, graph).icon;
48302             return icons[entity.id];
48303         }
48304
48305         function setClass(klass) {
48306             return function(entity) {
48307                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
48308             };
48309         }
48310
48311         function setAttributes(selection$$1) {
48312             ['shadow','stroke','fill'].forEach(function(klass) {
48313                 var rads = radiuses[klass];
48314                 selection$$1.selectAll('.' + klass)
48315                     .each(function(entity) {
48316                         var i = z && icon(entity),
48317                             c = i ? 0.5 : 0,
48318                             r = rads[i ? 3 : z];
48319                         this.setAttribute('cx', c);
48320                         this.setAttribute('cy', -c);
48321                         this.setAttribute('r', r);
48322                         if (i && klass === 'fill') {
48323                             this.setAttribute('visibility', 'hidden');
48324                         } else {
48325                             this.removeAttribute('visibility');
48326                         }
48327                     });
48328             });
48329
48330             selection$$1.selectAll('use')
48331                 .each(function() {
48332                     if (z) {
48333                         this.removeAttribute('visibility');
48334                     } else {
48335                         this.setAttribute('visibility', 'hidden');
48336                     }
48337                 });
48338         }
48339
48340
48341         var icons = {},
48342             z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
48343
48344         var groups = selection$$1
48345             .data(vertices, osmEntity$$1.key);
48346
48347         groups.exit()
48348             .remove();
48349
48350         var enter = groups.enter()
48351             .append('g')
48352             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
48353
48354         enter.append('circle')
48355             .each(setClass('shadow'));
48356
48357         enter.append('circle')
48358             .each(setClass('stroke'));
48359
48360         // Vertices with icons get a `use`.
48361         enter.filter(function(d) { return icon(d); })
48362             .append('use')
48363             .attr('transform', 'translate(-6, -6)')
48364             .attr('xlink:href', function(d) { return '#' + icon(d) + '-12'; })
48365             .attr('width', '12px')
48366             .attr('height', '12px')
48367             .each(setClass('icon'));
48368
48369         // Vertices with tags get a fill.
48370         enter.filter(function(d) { return d.hasInterestingTags(); })
48371             .append('circle')
48372             .each(setClass('fill'));
48373
48374         groups
48375             .merge(enter)
48376             .attr('transform', svgPointTransform(projection))
48377             .classed('shared', function(entity) { return graph.isShared(entity); })
48378             .call(setAttributes);
48379     }
48380
48381
48382     function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
48383         var selected = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
48384             wireframe = context.surface().classed('fill-wireframe'),
48385             vertices = [];
48386
48387         for (var i = 0; i < entities.length; i++) {
48388             var entity = entities[i],
48389                 geometry = entity.geometry(graph);
48390
48391             if (wireframe && geometry === 'point') {
48392                 vertices.push(entity);
48393                 continue;
48394             }
48395
48396             if (geometry !== 'vertex')
48397                 continue;
48398
48399             if (entity.id in selected ||
48400                 entity.hasInterestingTags() ||
48401                 entity.isIntersection(graph)) {
48402                 vertices.push(entity);
48403             }
48404         }
48405
48406         var layer = selection$$1.selectAll('.layer-hit');
48407         layer.selectAll('g.vertex.vertex-persistent')
48408             .filter(filter)
48409             .call(draw, vertices, 'vertex-persistent', graph, zoom$$1);
48410
48411         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48412     }
48413
48414
48415     function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
48416         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
48417         var layer = selection$$1.selectAll('.layer-hit');
48418
48419         layer.selectAll('g.vertex.vertex-hover')
48420             .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
48421     }
48422
48423
48424     drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
48425         if (target === hover) return;
48426         hover = target;
48427         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48428     };
48429
48430     return drawVertices;
48431 }
48432
48433 function behaviorEdit(context) {
48434
48435     function edit() {
48436         context.map()
48437             .minzoom(context.minEditableZoom());
48438     }
48439
48440
48441     edit.off = function() {
48442         context.map()
48443             .minzoom(0);
48444     };
48445
48446
48447     return edit;
48448 }
48449
48450 /*
48451    The hover behavior adds the `.hover` class on mouseover to all elements to which
48452    the identical datum is bound, and removes it on mouseout.
48453
48454    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
48455    representation may consist of several elements scattered throughout the DOM hierarchy.
48456    Only one of these elements can have the :hover pseudo-class, but all of them will
48457    have the .hover class.
48458  */
48459 function behaviorHover() {
48460     var dispatch$$1 = dispatch('hover'),
48461         selection$$1 = select(null),
48462         buttonDown,
48463         altDisables,
48464         target;
48465
48466
48467     function keydown() {
48468         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48469             dispatch$$1.call('hover', this, null);
48470             selection$$1.selectAll('.hover')
48471                 .classed('hover-suppressed', true)
48472                 .classed('hover', false);
48473         }
48474     }
48475
48476
48477     function keyup() {
48478         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48479             dispatch$$1.call('hover', this, target ? target.id : null);
48480             selection$$1.selectAll('.hover-suppressed')
48481                 .classed('hover-suppressed', false)
48482                 .classed('hover', true);
48483         }
48484     }
48485
48486
48487     var hover = function(__) {
48488         selection$$1 = __;
48489
48490         selection$$1
48491             .on('mouseover.hover', mouseover)
48492             .on('mouseout.hover', mouseout)
48493             .on('mousedown.hover', mousedown);
48494
48495         select(window)
48496             .on('keydown.hover', keydown)
48497             .on('keyup.hover', keyup);
48498
48499
48500         function mouseover() {
48501             if (buttonDown) return;
48502             var target = event.target;
48503             enter(target ? target.__data__ : null);
48504         }
48505
48506
48507         function mouseout() {
48508             if (buttonDown) return;
48509             var target = event.relatedTarget;
48510             enter(target ? target.__data__ : null);
48511         }
48512
48513
48514         function mousedown() {
48515             buttonDown = true;
48516             select(window)
48517                 .on('mouseup.hover', mouseup, true);
48518         }
48519
48520
48521         function mouseup() {
48522             buttonDown = false;
48523             select(window)
48524                 .on('mouseup.hover', null, true);
48525         }
48526
48527
48528         function enter(d) {
48529             if (d === target) return;
48530             target = d;
48531
48532             selection$$1.selectAll('.hover')
48533                 .classed('hover', false);
48534             selection$$1.selectAll('.hover-suppressed')
48535                 .classed('hover-suppressed', false);
48536
48537             if (target instanceof osmEntity$$1) {
48538                 var selector$$1 = '.' + target.id;
48539
48540                 if (target.type === 'relation') {
48541                     target.members.forEach(function(member) {
48542                         selector$$1 += ', .' + member.id;
48543                     });
48544                 }
48545
48546                 var suppressed = altDisables && event && event.altKey;
48547
48548                 selection$$1.selectAll(selector$$1)
48549                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
48550
48551                 dispatch$$1.call('hover', this, target.id);
48552             } else {
48553                 dispatch$$1.call('hover', this, null);
48554             }
48555         }
48556
48557     };
48558
48559
48560     hover.off = function(selection$$1) {
48561         selection$$1.selectAll('.hover')
48562             .classed('hover', false);
48563         selection$$1.selectAll('.hover-suppressed')
48564             .classed('hover-suppressed', false);
48565
48566         selection$$1
48567             .on('mouseover.hover', null)
48568             .on('mouseout.hover', null)
48569             .on('mousedown.hover', null);
48570
48571         select(window)
48572             .on('keydown.hover', null)
48573             .on('keyup.hover', null);
48574     };
48575
48576
48577     hover.altDisables = function(_) {
48578         if (!arguments.length) return altDisables;
48579         altDisables = _;
48580         return hover;
48581     };
48582
48583
48584     return utilRebind(hover, dispatch$$1, 'on');
48585 }
48586
48587 function behaviorTail() {
48588     var text$$1,
48589         container,
48590         xmargin = 25,
48591         tooltipSize = [0, 0],
48592         selectionSize = [0, 0];
48593
48594
48595     function tail(selection$$1) {
48596         if (!text$$1) return;
48597
48598         select(window)
48599             .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
48600
48601         container = select(document.body)
48602             .append('div')
48603             .style('display', 'none')
48604             .attr('class', 'tail tooltip-inner');
48605
48606         container.append('div')
48607             .text(text$$1);
48608
48609         selection$$1
48610             .on('mousemove.tail', mousemove)
48611             .on('mouseenter.tail', mouseenter)
48612             .on('mouseleave.tail', mouseleave);
48613
48614         container
48615             .on('mousemove.tail', mousemove);
48616
48617         tooltipSize = utilGetDimensions(container);
48618         selectionSize = utilGetDimensions(selection$$1);
48619
48620
48621         function show() {
48622             container.style('display', 'block');
48623             tooltipSize = utilGetDimensions(container);
48624         }
48625
48626
48627         function mousemove() {
48628             if (container.style('display') === 'none') show();
48629             var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
48630                 -tooltipSize[0] - xmargin : xmargin;
48631             container.classed('left', xoffset > 0);
48632             utilSetTransform(container, event.clientX + xoffset, event.clientY);
48633         }
48634
48635
48636         function mouseleave() {
48637             if (event.relatedTarget !== container.node()) {
48638                 container.style('display', 'none');
48639             }
48640         }
48641
48642
48643         function mouseenter() {
48644             if (event.relatedTarget !== container.node()) {
48645                 show();
48646             }
48647         }
48648     }
48649
48650
48651     tail.off = function(selection$$1) {
48652         if (!text$$1) return;
48653
48654         container
48655             .on('mousemove.tail', null)
48656             .remove();
48657
48658         selection$$1
48659             .on('mousemove.tail', null)
48660             .on('mouseenter.tail', null)
48661             .on('mouseleave.tail', null);
48662
48663         select(window)
48664             .on('resize.tail', null);
48665     };
48666
48667
48668     tail.text = function(_) {
48669         if (!arguments.length) return text$$1;
48670         text$$1 = _;
48671         return tail;
48672     };
48673
48674
48675     return tail;
48676 }
48677
48678 behaviorDraw.usedTails = {};
48679 behaviorDraw.disableSpace = false;
48680 behaviorDraw.lastSpace = null;
48681
48682
48683 function behaviorDraw(context) {
48684     var dispatch$$1 = dispatch('move', 'click', 'clickWay',
48685             'clickNode', 'undo', 'cancel', 'finish'),
48686         keybinding = d3keybinding('draw'),
48687         hover = behaviorHover(context)
48688             .altDisables(true)
48689             .on('hover', context.ui().sidebar.hover),
48690         tail = behaviorTail(),
48691         edit = behaviorEdit(context),
48692         closeTolerance = 4,
48693         tolerance = 12,
48694         mouseLeave = false,
48695         lastMouse = null,
48696         cached = behaviorDraw;
48697
48698
48699     function datum() {
48700         if (event.altKey) return {};
48701
48702         if (event.type === 'keydown') {
48703             return (lastMouse && lastMouse.target.__data__) || {};
48704         } else {
48705             return event.target.__data__ || {};
48706         }
48707     }
48708
48709
48710     function mousedown() {
48711
48712         function point() {
48713             var p = context.container().node();
48714             return touchId !== null ? touches(p).filter(function(p) {
48715                 return p.identifier === touchId;
48716             })[0] : mouse(p);
48717         }
48718
48719         var element = select(this),
48720             touchId = event.touches ? event.changedTouches[0].identifier : null,
48721             t1 = +new Date(),
48722             p1 = point();
48723
48724         element.on('mousemove.draw', null);
48725
48726         select(window).on('mouseup.draw', function() {
48727             var t2 = +new Date(),
48728                 p2 = point(),
48729                 dist = geoEuclideanDistance(p1, p2);
48730
48731             element.on('mousemove.draw', mousemove);
48732             select(window).on('mouseup.draw', null);
48733
48734             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
48735                 // Prevent a quick second click
48736                 select(window).on('click.draw-block', function() {
48737                     event.stopPropagation();
48738                 }, true);
48739
48740                 context.map().dblclickEnable(false);
48741
48742                 window.setTimeout(function() {
48743                     context.map().dblclickEnable(true);
48744                     select(window).on('click.draw-block', null);
48745                 }, 500);
48746
48747                 click();
48748             }
48749         }, true);
48750     }
48751
48752
48753     function mousemove() {
48754         lastMouse = event;
48755         dispatch$$1.call('move', this, datum());
48756     }
48757
48758
48759     function mouseenter() {
48760         mouseLeave = false;
48761     }
48762
48763
48764     function mouseleave() {
48765         mouseLeave = true;
48766     }
48767
48768
48769     function click() {
48770         var d = datum();
48771         if (d.type === 'way') {
48772             var dims = context.map().dimensions(),
48773                 mouse$$1 = context.mouse(),
48774                 pad = 5,
48775                 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
48776                     mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
48777
48778             if (trySnap) {
48779                 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
48780                     edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
48781                 dispatch$$1.call('clickWay', this, choice.loc, edge);
48782             } else {
48783                 dispatch$$1.call('click', this, context.map().mouseCoordinates());
48784             }
48785
48786         } else if (d.type === 'node') {
48787             dispatch$$1.call('clickNode', this, d);
48788
48789         } else {
48790             dispatch$$1.call('click', this, context.map().mouseCoordinates());
48791         }
48792     }
48793
48794
48795     function space() {
48796         var currSpace = context.mouse();
48797         if (cached.disableSpace && cached.lastSpace) {
48798             var dist = geoEuclideanDistance(cached.lastSpace, currSpace);
48799             if (dist > tolerance) {
48800                 cached.disableSpace = false;
48801             }
48802         }
48803
48804         if (cached.disableSpace || mouseLeave || !lastMouse) return;
48805
48806         // user must move mouse or release space bar to allow another click
48807         cached.lastSpace = currSpace;
48808         cached.disableSpace = true;
48809
48810         select(window).on('keyup.space-block', function() {
48811             cached.disableSpace = false;
48812             select(window).on('keyup.space-block', null);
48813         });
48814
48815         event.preventDefault();
48816         click();
48817     }
48818
48819
48820     function backspace() {
48821         event.preventDefault();
48822         dispatch$$1.call('undo');
48823     }
48824
48825
48826     function del() {
48827         event.preventDefault();
48828         dispatch$$1.call('cancel');
48829     }
48830
48831
48832     function ret() {
48833         event.preventDefault();
48834         dispatch$$1.call('finish');
48835     }
48836
48837
48838     function draw(selection$$1) {
48839         context.install(hover);
48840         context.install(edit);
48841
48842         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
48843             context.install(tail);
48844         }
48845
48846         keybinding
48847             .on('⌫', backspace)
48848             .on('⌦', del)
48849             .on('⎋', ret)
48850             .on('↩', ret)
48851             .on('space', space)
48852             .on('⌥space', space);
48853
48854         selection$$1
48855             .on('mouseenter.draw', mouseenter)
48856             .on('mouseleave.draw', mouseleave)
48857             .on('mousedown.draw', mousedown)
48858             .on('mousemove.draw', mousemove);
48859
48860         select(document)
48861             .call(keybinding);
48862
48863         return draw;
48864     }
48865
48866
48867     draw.off = function(selection$$1) {
48868         context.ui().sidebar.hover.cancel();
48869         context.uninstall(hover);
48870         context.uninstall(edit);
48871
48872         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
48873             context.uninstall(tail);
48874             cached.usedTails[tail.text()] = true;
48875         }
48876
48877         selection$$1
48878             .on('mouseenter.draw', null)
48879             .on('mouseleave.draw', null)
48880             .on('mousedown.draw', null)
48881             .on('mousemove.draw', null);
48882
48883         select(window)
48884             .on('mouseup.draw', null);
48885             // note: keyup.space-block, click.draw-block should remain
48886
48887         select(document)
48888             .call(keybinding.off);
48889     };
48890
48891
48892     draw.tail = function(_) {
48893         tail.text(_);
48894         return draw;
48895     };
48896
48897
48898     return utilRebind(draw, dispatch$$1, 'on');
48899 }
48900
48901 function behaviorAddWay(context) {
48902     var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
48903         draw = behaviorDraw(context);
48904
48905     var addWay = function(surface) {
48906         draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
48907             .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
48908             .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
48909             .on('cancel', addWay.cancel)
48910             .on('finish', addWay.cancel);
48911
48912         context.map()
48913             .dblclickEnable(false);
48914
48915         surface.call(draw);
48916     };
48917
48918
48919     addWay.off = function(surface) {
48920         surface.call(draw.off);
48921     };
48922
48923
48924     addWay.cancel = function() {
48925         window.setTimeout(function() {
48926             context.map().dblclickEnable(true);
48927         }, 1000);
48928
48929         context.enter(modeBrowse$$1(context));
48930     };
48931
48932
48933     addWay.tail = function(text$$1) {
48934         draw.tail(text$$1);
48935         return addWay;
48936     };
48937
48938
48939     return utilRebind(addWay, dispatch$$1, 'on');
48940 }
48941
48942 function behaviorBreathe() {
48943     var duration = 800,
48944         steps = 4,
48945         selector$$1 = '.selected.shadow, .selected .shadow',
48946         selected = select(null),
48947         classed = '',
48948         params = {},
48949         done = false,
48950         timer$$1;
48951
48952
48953     // This is a workaround for a bug in rollup v0.36
48954     // https://github.com/rollup/rollup/issues/984
48955     // The symbol for this default export is not used anywhere, but it
48956     // needs to be called in order to be included in the bundle.
48957     var t = transition();
48958
48959
48960     function ratchetyInterpolator(a, b, steps, units) {
48961         a = parseFloat(a);
48962         b = parseFloat(b);
48963         var sample = quantize$1()
48964             .domain([0, 1])
48965             .range(quantize(interpolateNumber(a, b), steps));
48966
48967         return function(t) {
48968             return String(sample(t)) + (units || '');
48969         };
48970     }
48971
48972
48973     function reset(selection$$1) {
48974         selection$$1
48975             .style('stroke-opacity', null)
48976             .style('stroke-width', null)
48977             .style('fill-opacity', null)
48978             .style('r', null);
48979     }
48980
48981
48982     function setAnimationParams(transition$$1, fromTo) {
48983         var toFrom = (fromTo === 'from' ? 'to' : 'from');
48984
48985         transition$$1
48986             .styleTween('stroke-opacity', function(d) {
48987                 return ratchetyInterpolator(
48988                     params[d.id][toFrom].opacity,
48989                     params[d.id][fromTo].opacity,
48990                     steps
48991                 );
48992             })
48993             .styleTween('stroke-width', function(d) {
48994                 return ratchetyInterpolator(
48995                     params[d.id][toFrom].width,
48996                     params[d.id][fromTo].width,
48997                     steps,
48998                     'px'
48999                 );
49000             })
49001             .styleTween('fill-opacity', function(d) {
49002                 return ratchetyInterpolator(
49003                     params[d.id][toFrom].opacity,
49004                     params[d.id][fromTo].opacity,
49005                     steps
49006                 );
49007             })
49008             .styleTween('r', function(d) {
49009                 return ratchetyInterpolator(
49010                     params[d.id][toFrom].width,
49011                     params[d.id][fromTo].width,
49012                     steps,
49013                     'px'
49014                 );
49015             });
49016     }
49017
49018
49019     function calcAnimationParams(selection$$1) {
49020         selection$$1
49021             .call(reset)
49022             .each(function(d) {
49023                 var s = select(this),
49024                     tag = s.node().tagName,
49025                     p = {'from': {}, 'to': {}},
49026                     opacity, width;
49027
49028                 // determine base opacity and width
49029                 if (tag === 'circle') {
49030                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
49031                     width = parseFloat(s.style('r') || 15.5);
49032                 } else {
49033                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
49034                     width = parseFloat(s.style('stroke-width') || 10);
49035                 }
49036
49037                 // calculate from/to interpolation params..
49038                 p.tag = tag;
49039                 p.from.opacity = opacity * 0.6;
49040                 p.to.opacity = opacity * 1.25;
49041                 p.from.width = width * 0.9;
49042                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
49043                 params[d.id] = p;
49044             });
49045     }
49046
49047
49048     function run(surface, fromTo) {
49049         var toFrom = (fromTo === 'from' ? 'to' : 'from'),
49050             currSelected = surface.selectAll(selector$$1),
49051             currClassed = surface.attr('class');
49052
49053         if (done || currSelected.empty()) {
49054             selected.call(reset);
49055             return;
49056         }
49057
49058         if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
49059             selected.call(reset);
49060             classed = currClassed;
49061             selected = currSelected.call(calcAnimationParams);
49062         }
49063
49064         selected
49065             .transition()
49066             .duration(duration)
49067             .call(setAnimationParams, fromTo)
49068             .on('end', function() {
49069                 surface.call(run, toFrom);
49070             });
49071     }
49072
49073
49074     var breathe = function(surface) {
49075         done = false;
49076         timer$$1 = timer(function() {
49077             // wait for elements to actually become selected
49078             if (surface.selectAll(selector$$1).empty()) {
49079                 return false;
49080             }
49081
49082             surface.call(run, 'from');
49083             timer$$1.stop();
49084             return true;
49085         }, 20);
49086     };
49087
49088
49089     breathe.off = function() {
49090         done = true;
49091         if (timer$$1) {
49092             timer$$1.stop();
49093         }
49094         selected
49095             .interrupt()
49096             .call(reset);
49097     };
49098
49099
49100     return breathe;
49101 }
49102
49103 function behaviorCopy(context) {
49104     var keybinding = d3keybinding('copy');
49105
49106
49107     function groupEntities(ids, graph) {
49108         var entities = ids.map(function (id) { return graph.entity(id); });
49109         return lodash.extend({relation: [], way: [], node: []},
49110             lodash.groupBy(entities, function(entity) { return entity.type; }));
49111     }
49112
49113
49114     function getDescendants(id, graph, descendants) {
49115         var entity = graph.entity(id),
49116             i, children;
49117
49118         descendants = descendants || {};
49119
49120         if (entity.type === 'relation') {
49121             children = lodash.map(entity.members, 'id');
49122         } else if (entity.type === 'way') {
49123             children = entity.nodes;
49124         } else {
49125             children = [];
49126         }
49127
49128         for (i = 0; i < children.length; i++) {
49129             if (!descendants[children[i]]) {
49130                 descendants[children[i]] = true;
49131                 descendants = getDescendants(children[i], graph, descendants);
49132             }
49133         }
49134
49135         return descendants;
49136     }
49137
49138
49139     function doCopy() {
49140         event.preventDefault();
49141         if (context.inIntro()) return;
49142
49143         var graph = context.graph(),
49144             selected = groupEntities(context.selectedIDs(), graph),
49145             canCopy = [],
49146             skip = {},
49147             i, entity;
49148
49149         for (i = 0; i < selected.relation.length; i++) {
49150             entity = selected.relation[i];
49151             if (!skip[entity.id] && entity.isComplete(graph)) {
49152                 canCopy.push(entity.id);
49153                 skip = getDescendants(entity.id, graph, skip);
49154             }
49155         }
49156         for (i = 0; i < selected.way.length; i++) {
49157             entity = selected.way[i];
49158             if (!skip[entity.id]) {
49159                 canCopy.push(entity.id);
49160                 skip = getDescendants(entity.id, graph, skip);
49161             }
49162         }
49163         for (i = 0; i < selected.node.length; i++) {
49164             entity = selected.node[i];
49165             if (!skip[entity.id]) {
49166                 canCopy.push(entity.id);
49167             }
49168         }
49169
49170         context.copyIDs(canCopy);
49171     }
49172
49173
49174     function copy() {
49175         keybinding.on(uiCmd('⌘C'), doCopy);
49176         select(document).call(keybinding);
49177         return copy;
49178     }
49179
49180
49181     copy.off = function() {
49182         select(document).call(keybinding.off);
49183     };
49184
49185
49186     return copy;
49187 }
49188
49189 /*
49190     `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
49191
49192     * The `origin` function is expected to return an [x, y] tuple rather than an
49193       {x, y} object.
49194     * The events are `start`, `move`, and `end`.
49195       (https://github.com/mbostock/d3/issues/563)
49196     * The `start` event is not dispatched until the first cursor movement occurs.
49197       (https://github.com/mbostock/d3/pull/368)
49198     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
49199       than `x`, `y`, `dx`, and `dy` properties.
49200     * The `end` event is not dispatched if no movement occurs.
49201     * An `off` function is available that unbinds the drag's internal event handlers.
49202     * Delegation is supported via the `delegate` function.
49203
49204  */
49205 function behaviorDrag() {
49206     var event$$1 = dispatch('start', 'move', 'end'),
49207         origin = null,
49208         selector$$1 = '',
49209         filter = null,
49210         event_, target, surface;
49211
49212
49213     function d3_eventCancel() {
49214         event.stopPropagation();
49215         event.preventDefault();
49216     }
49217
49218     function eventOf(thiz, argumentz) {
49219         return function(e1) {
49220             e1.target = drag$$1;
49221             customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
49222         };
49223     }
49224
49225     var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
49226         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
49227             function () {
49228                 var selection$$1 = selection(),
49229                     select$$1 = selection$$1.style(d3_event_userSelectProperty);
49230                 selection$$1.style(d3_event_userSelectProperty, 'none');
49231                 return function () {
49232                     selection$$1.style(d3_event_userSelectProperty, select$$1);
49233                 };
49234             } :
49235             function (type) {
49236                 var w = select(window).on('selectstart.' + type, d3_eventCancel);
49237                 return function () {
49238                     w.on('selectstart.' + type, null);
49239                 };
49240             };
49241
49242
49243     function mousedown() {
49244         target = this;
49245         event_ = eventOf(target, arguments);
49246
49247         var eventTarget = event.target,
49248             touchId = event.touches ? event.changedTouches[0].identifier : null,
49249             offset,
49250             origin_ = point(),
49251             started = false,
49252             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
49253
49254         var w = select(window)
49255             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
49256             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
49257
49258         if (origin) {
49259             offset = origin.apply(target, arguments);
49260             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
49261         } else {
49262             offset = [0, 0];
49263         }
49264
49265         if (touchId === null) event.stopPropagation();
49266
49267         function point() {
49268             var p = target.parentNode || surface;
49269             return touchId !== null ? touches(p).filter(function(p) {
49270                 return p.identifier === touchId;
49271             })[0] : mouse(p);
49272         }
49273
49274
49275         function dragmove() {
49276             var p = point(),
49277                 dx = p[0] - origin_[0],
49278                 dy = p[1] - origin_[1];
49279
49280             if (dx === 0 && dy === 0)
49281                 return;
49282
49283             if (!started) {
49284                 started = true;
49285                 event_({
49286                     type: 'start'
49287                 });
49288             }
49289
49290             origin_ = p;
49291             d3_eventCancel();
49292
49293             event_({
49294                 type: 'move',
49295                 point: [p[0] + offset[0],  p[1] + offset[1]],
49296                 delta: [dx, dy]
49297             });
49298         }
49299
49300
49301         function dragend() {
49302             if (started) {
49303                 event_({
49304                     type: 'end'
49305                 });
49306
49307                 d3_eventCancel();
49308                 if (event.target === eventTarget) w.on('click.drag', click, true);
49309             }
49310
49311             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
49312                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
49313             selectEnable();
49314         }
49315
49316
49317         function click() {
49318             d3_eventCancel();
49319             w.on('click.drag', null);
49320         }
49321     }
49322
49323
49324     function drag$$1(selection$$1) {
49325         var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
49326             delegate = mousedown;
49327
49328         if (selector$$1) {
49329             delegate = function() {
49330                 var root = this,
49331                     target = event.target;
49332                 for (; target && target !== root; target = target.parentNode) {
49333                     if (target[matchesSelector](selector$$1) &&
49334                             (!filter || filter(target.__data__))) {
49335                         return mousedown.call(target, target.__data__);
49336                     }
49337                 }
49338             };
49339         }
49340
49341         selection$$1.on('mousedown.drag' + selector$$1, delegate)
49342             .on('touchstart.drag' + selector$$1, delegate);
49343     }
49344
49345
49346     drag$$1.off = function(selection$$1) {
49347         selection$$1.on('mousedown.drag' + selector$$1, null)
49348             .on('touchstart.drag' + selector$$1, null);
49349     };
49350
49351
49352     drag$$1.delegate = function(_) {
49353         if (!arguments.length) return selector$$1;
49354         selector$$1 = _;
49355         return drag$$1;
49356     };
49357
49358
49359     drag$$1.filter = function(_) {
49360         if (!arguments.length) return origin;
49361         filter = _;
49362         return drag$$1;
49363     };
49364
49365
49366     drag$$1.origin = function (_) {
49367         if (!arguments.length) return origin;
49368         origin = _;
49369         return drag$$1;
49370     };
49371
49372
49373     drag$$1.cancel = function() {
49374         select(window)
49375             .on('mousemove.drag', null)
49376             .on('mouseup.drag', null);
49377         return drag$$1;
49378     };
49379
49380
49381     drag$$1.target = function() {
49382         if (!arguments.length) return target;
49383         target = arguments[0];
49384         event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
49385         return drag$$1;
49386     };
49387
49388
49389     drag$$1.surface = function() {
49390         if (!arguments.length) return surface;
49391         surface = arguments[0];
49392         return drag$$1;
49393     };
49394
49395
49396     return utilRebind(drag$$1, event$$1, 'on');
49397 }
49398
49399 function behaviorDrawWay(context, wayId, index, mode, baseGraph) {
49400
49401     var way = context.entity(wayId),
49402         isArea = context.geometry(wayId) === 'area',
49403         finished = false,
49404         annotation = t((way.isDegenerate() ?
49405             'operations.start.annotation.' :
49406             'operations.continue.annotation.') + context.geometry(wayId)),
49407         draw = behaviorDraw(context);
49408
49409     var startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0,
49410         start = osmNode({loc: context.graph().entity(way.nodes[startIndex]).loc}),
49411         end = osmNode({loc: context.map().mouseCoordinates()}),
49412         segment = osmWay({
49413             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
49414             tags: lodash.clone(way.tags)
49415         });
49416
49417     var fn = context[way.isDegenerate() ? 'replace' : 'perform'];
49418     if (isArea) {
49419         fn(actionAddEntity(end),
49420             actionAddVertex(wayId, end.id, index)
49421         );
49422     } else {
49423         fn(actionAddEntity(start),
49424             actionAddEntity(end),
49425             actionAddEntity(segment)
49426         );
49427     }
49428
49429
49430     function move(datum) {
49431         var loc;
49432
49433         if (datum.type === 'node' && datum.id !== end.id) {
49434             loc = datum.loc;
49435
49436         } else if (datum.type === 'way' && datum.id !== segment.id) {
49437             var dims = context.map().dimensions(),
49438                 mouse = context.mouse(),
49439                 pad = 5,
49440                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
49441                     mouse[1] > pad && mouse[1] < dims[1] - pad;
49442
49443             if (trySnap) {
49444                 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
49445             }
49446         }
49447
49448         if (!loc) {
49449             loc = context.map().mouseCoordinates();
49450         }
49451
49452         context.replace(actionMoveNode(end.id, loc));
49453     }
49454
49455
49456     function undone() {
49457         finished = true;
49458         context.enter(modeBrowse$$1(context));
49459     }
49460
49461
49462     function setActiveElements() {
49463         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
49464         context.surface().selectAll(utilEntitySelector(active))
49465             .classed('active', true);
49466     }
49467
49468
49469     var drawWay = function(surface) {
49470         draw.on('move', move)
49471             .on('click', drawWay.add)
49472             .on('clickWay', drawWay.addWay)
49473             .on('clickNode', drawWay.addNode)
49474             .on('undo', context.undo)
49475             .on('cancel', drawWay.cancel)
49476             .on('finish', drawWay.finish);
49477
49478         context.map()
49479             .dblclickEnable(false)
49480             .on('drawn.draw', setActiveElements);
49481
49482         setActiveElements();
49483
49484         surface.call(draw);
49485
49486         context.history()
49487             .on('undone.draw', undone);
49488     };
49489
49490
49491     drawWay.off = function(surface) {
49492         if (!finished)
49493             context.pop();
49494
49495         context.map()
49496             .on('drawn.draw', null);
49497
49498         surface.call(draw.off)
49499             .selectAll('.active')
49500             .classed('active', false);
49501
49502         context.history()
49503             .on('undone.draw', null);
49504     };
49505
49506
49507     function ReplaceTemporaryNode(newNode) {
49508         return function(graph) {
49509             if (isArea) {
49510                 return graph
49511                     .replace(way.addNode(newNode.id, index))
49512                     .remove(end);
49513
49514             } else {
49515                 return graph
49516                     .replace(graph.entity(wayId).addNode(newNode.id, index))
49517                     .remove(end)
49518                     .remove(segment)
49519                     .remove(start);
49520             }
49521         };
49522     }
49523
49524
49525     // Accept the current position of the temporary node and continue drawing.
49526     drawWay.add = function(loc) {
49527         // prevent duplicate nodes
49528         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
49529         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
49530
49531         var newNode = osmNode({loc: loc});
49532
49533         context.replace(
49534             actionAddEntity(newNode),
49535             ReplaceTemporaryNode(newNode),
49536             annotation
49537         );
49538
49539         finished = true;
49540         context.enter(mode);
49541     };
49542
49543
49544     // Connect the way to an existing way.
49545     drawWay.addWay = function(loc, edge) {
49546         var previousEdge = startIndex ?
49547             [way.nodes[startIndex], way.nodes[startIndex - 1]] :
49548             [way.nodes[0], way.nodes[1]];
49549
49550         // Avoid creating duplicate segments
49551         if (!isArea && geoEdgeEqual(edge, previousEdge))
49552             return;
49553
49554         var newNode = osmNode({ loc: loc });
49555
49556         context.perform(
49557             actionAddMidpoint({ loc: loc, edge: edge}, newNode),
49558             ReplaceTemporaryNode(newNode),
49559             annotation
49560         );
49561
49562         finished = true;
49563         context.enter(mode);
49564     };
49565
49566
49567     // Connect the way to an existing node and continue drawing.
49568     drawWay.addNode = function(node) {
49569         // Avoid creating duplicate segments
49570         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
49571
49572         context.perform(
49573             ReplaceTemporaryNode(node),
49574             annotation
49575         );
49576
49577         finished = true;
49578         context.enter(mode);
49579     };
49580
49581
49582     // Finish the draw operation, removing the temporary node. If the way has enough
49583     // nodes to be valid, it's selected. Otherwise, return to browse mode.
49584     drawWay.finish = function() {
49585         context.pop();
49586         finished = true;
49587
49588         window.setTimeout(function() {
49589             context.map().dblclickEnable(true);
49590         }, 1000);
49591
49592         if (context.hasEntity(wayId)) {
49593             context.enter(
49594                 modeSelect(context, [wayId]).suppressMenu(true).newFeature(true)
49595             );
49596         } else {
49597             context.enter(modeBrowse$$1(context));
49598         }
49599     };
49600
49601
49602     // Cancel the draw operation and return to browse, deleting everything drawn.
49603     drawWay.cancel = function() {
49604         context.perform(
49605             utilFunctor(baseGraph),
49606             t('operations.cancel_draw.annotation'));
49607
49608         window.setTimeout(function() {
49609             context.map().dblclickEnable(true);
49610         }, 1000);
49611
49612         finished = true;
49613         context.enter(modeBrowse$$1(context));
49614     };
49615
49616
49617     drawWay.tail = function(text) {
49618         draw.tail(text);
49619         return drawWay;
49620     };
49621
49622
49623     return drawWay;
49624 }
49625
49626 function behaviorHash(context) {
49627     var s0 = null, // cached window.location.hash
49628         lat = 90 - 1e-8; // allowable latitude range
49629
49630
49631     var parser = function(map$$1, s) {
49632         var q = utilStringQs(s);
49633         var args = (q.map || '').split('/').map(Number);
49634         if (args.length < 3 || args.some(isNaN)) {
49635             return true; // replace bogus hash
49636         } else if (s !== formatter(map$$1).slice(1)) {
49637             map$$1.centerZoom([args[2],
49638                 Math.min(lat, Math.max(-lat, args[1]))], args[0]);
49639         }
49640     };
49641
49642
49643     var formatter = function(map$$1) {
49644         var mode = context.mode(),
49645             center = map$$1.center(),
49646             zoom$$1 = map$$1.zoom(),
49647             precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
49648             q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
49649             newParams = {};
49650
49651         if (mode && mode.id === 'browse') {
49652             delete q.id;
49653         } else {
49654             var selected = context.selectedIDs().filter(function(id) {
49655                 return !context.entity(id).isNew();
49656             });
49657             if (selected.length) {
49658                 newParams.id = selected.join(',');
49659             }
49660         }
49661
49662         newParams.map = zoom$$1.toFixed(2) +
49663                 '/' + center[1].toFixed(precision) +
49664                 '/' + center[0].toFixed(precision);
49665
49666         return '#' + utilQsString(lodash.assign(q, newParams), true);
49667     };
49668
49669
49670     function update() {
49671         if (context.inIntro()) return;
49672         var s1 = formatter(context.map());
49673         if (s0 !== s1) {
49674             window.location.replace(s0 = s1);  // don't recenter the map!
49675         }
49676     }
49677
49678
49679     var throttledUpdate = lodash.throttle(update, 500);
49680
49681
49682     function hashchange() {
49683         if (window.location.hash === s0) return;  // ignore spurious hashchange events
49684         if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
49685             update(); // replace bogus hash
49686         }
49687     }
49688
49689
49690     function hash() {
49691         context.map()
49692             .on('move.hash', throttledUpdate);
49693
49694         context
49695             .on('enter.hash', throttledUpdate);
49696
49697         select(window)
49698             .on('hashchange.hash', hashchange);
49699
49700         if (window.location.hash) {
49701             var q = utilStringQs(window.location.hash.substring(1));
49702             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
49703             if (q.comment) context.storage('comment', q.comment);
49704             hashchange();
49705             if (q.map) hash.hadHash = true;
49706         }
49707     }
49708
49709
49710     hash.off = function() {
49711         throttledUpdate.cancel();
49712
49713         context.map()
49714             .on('move.hash', null);
49715
49716         context
49717             .on('enter.hash', null);
49718
49719         select(window)
49720             .on('hashchange.hash', null);
49721
49722         window.location.hash = '';
49723     };
49724
49725
49726     return hash;
49727 }
49728
49729 function behaviorLasso(context) {
49730
49731     var behavior = function(selection$$1) {
49732         var lasso;
49733
49734
49735         function mousedown() {
49736             var button = 0;  // left
49737             if (event.button === button && event.shiftKey === true) {
49738                 lasso = null;
49739
49740                 selection$$1
49741                     .on('mousemove.lasso', mousemove)
49742                     .on('mouseup.lasso', mouseup);
49743
49744                 event.stopPropagation();
49745             }
49746         }
49747
49748
49749         function mousemove() {
49750             if (!lasso) {
49751                 lasso = uiLasso(context);
49752                 context.surface().call(lasso);
49753             }
49754
49755             lasso.p(context.mouse());
49756         }
49757
49758
49759         function normalize(a, b) {
49760             return [
49761                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
49762                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
49763         }
49764
49765
49766         function lassoed() {
49767             if (!lasso) return [];
49768
49769             var graph = context.graph(),
49770                 bounds = lasso.extent().map(context.projection.invert),
49771                 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
49772
49773             return lodash.map(context.intersects(extent$$1).filter(function(entity) {
49774                 return entity.type === 'node' &&
49775                     geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
49776                     !context.features().isHidden(entity, graph, entity.geometry(graph));
49777             }), 'id');
49778         }
49779
49780
49781         function mouseup() {
49782             selection$$1
49783                 .on('mousemove.lasso', null)
49784                 .on('mouseup.lasso', null);
49785
49786             if (!lasso) return;
49787
49788             var ids = lassoed();
49789             lasso.close();
49790
49791             if (ids.length) {
49792                 context.enter(modeSelect(context, ids));
49793             }
49794         }
49795
49796         selection$$1
49797             .on('mousedown.lasso', mousedown);
49798     };
49799
49800
49801     behavior.off = function(selection$$1) {
49802         selection$$1.on('mousedown.lasso', null);
49803     };
49804
49805
49806     return behavior;
49807 }
49808
49809 function behaviorPaste(context) {
49810     var keybinding = d3keybinding('paste');
49811
49812     function omitTag(v, k) {
49813         return (
49814             k === 'phone' ||
49815             k === 'fax' ||
49816             k === 'email' ||
49817             k === 'website' ||
49818             k === 'url' ||
49819             k === 'note' ||
49820             k === 'description' ||
49821             k.indexOf('name') !== -1 ||
49822             k.indexOf('wiki') === 0 ||
49823             k.indexOf('addr:') === 0 ||
49824             k.indexOf('contact:') === 0
49825         );
49826     }
49827
49828
49829     function doPaste() {
49830         event.preventDefault();
49831         if (context.inIntro()) return;
49832
49833         var baseGraph = context.graph(),
49834             mouse$$1 = context.mouse(),
49835             projection = context.projection,
49836             viewport = geoExtent$$1(projection.clipExtent()).polygon();
49837
49838         if (!geoPointInPolygon(mouse$$1, viewport)) return;
49839
49840         var extent$$1 = geoExtent$$1(),
49841             oldIDs = context.copyIDs(),
49842             oldGraph = context.copyGraph(),
49843             newIDs = [];
49844
49845         if (!oldIDs.length) return;
49846
49847         var action = actionCopyEntities(oldIDs, oldGraph);
49848         context.perform(action);
49849
49850         var copies = action.copies();
49851         for (var id in copies) {
49852             var oldEntity = oldGraph.entity(id),
49853                 newEntity = copies[id];
49854
49855             extent$$1._extend(oldEntity.extent(oldGraph));
49856             newIDs.push(newEntity.id);
49857             context.perform(
49858                 actionChangeTags(newEntity.id, lodash.omit(newEntity.tags, omitTag))
49859             );
49860         }
49861
49862         // Put pasted objects where mouse pointer is..
49863         var center = projection(extent$$1.center()),
49864             delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
49865
49866         context.perform(actionMove(newIDs, delta, projection));
49867         context.enter(modeMove$$1(context, newIDs, baseGraph));
49868     }
49869
49870
49871     function paste() {
49872         keybinding.on(uiCmd('⌘V'), doPaste);
49873         select(document).call(keybinding);
49874         return paste;
49875     }
49876
49877
49878     paste.off = function() {
49879         select(document).call(keybinding.off);
49880     };
49881
49882
49883     return paste;
49884 }
49885
49886 function behaviorSelect(context) {
49887
49888     function keydown() {
49889         if (event && event.shiftKey) {
49890             context.surface()
49891                 .classed('behavior-multiselect', true);
49892         }
49893     }
49894
49895
49896     function keyup() {
49897         if (!event || !event.shiftKey) {
49898             context.surface()
49899                 .classed('behavior-multiselect', false);
49900         }
49901     }
49902
49903
49904     function click() {
49905         var datum = event.target.__data__,
49906             lasso = select('#surface .lasso').node(),
49907             mode = context.mode();
49908
49909         if (!(datum instanceof osmEntity$$1)) {
49910             if (!event.shiftKey && !lasso && mode.id !== 'browse')
49911                 context.enter(modeBrowse$$1(context));
49912
49913         } else if (!event.shiftKey && !lasso) {
49914             // Avoid re-entering Select mode with same entity.
49915             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
49916                 context.enter(modeSelect(context, [datum.id]));
49917             } else {
49918                 mode.suppressMenu(false).reselect();
49919             }
49920         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
49921             var selectedIDs = lodash.without(context.selectedIDs(), datum.id);
49922             context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse$$1(context));
49923
49924         } else {
49925             context.enter(modeSelect(context, context.selectedIDs().concat([datum.id])));
49926         }
49927     }
49928
49929
49930     var behavior = function(selection$$1) {
49931         select(window)
49932             .on('keydown.select', keydown)
49933             .on('keyup.select', keyup);
49934
49935         selection$$1.on('click.select', click);
49936
49937         keydown();
49938     };
49939
49940
49941     behavior.off = function(selection$$1) {
49942         select(window)
49943             .on('keydown.select', null)
49944             .on('keyup.select', null);
49945
49946         selection$$1.on('click.select', null);
49947
49948         keyup();
49949     };
49950
49951
49952     return behavior;
49953 }
49954
49955 function modeAddArea$$1(context) {
49956     var mode = {
49957         id: 'add-area',
49958         button: 'area',
49959         title: t('modes.add_area.title'),
49960         description: t('modes.add_area.description'),
49961         key: '3'
49962     };
49963
49964     var behavior = behaviorAddWay(context)
49965             .tail(t('modes.add_area.tail'))
49966             .on('start', start)
49967             .on('startFromWay', startFromWay)
49968             .on('startFromNode', startFromNode),
49969         defaultTags = { area: 'yes' };
49970
49971
49972     function start(loc) {
49973         var graph = context.graph(),
49974             node = osmNode({ loc: loc }),
49975             way = osmWay({ tags: defaultTags });
49976
49977         context.perform(
49978             actionAddEntity(node),
49979             actionAddEntity(way),
49980             actionAddVertex(way.id, node.id),
49981             actionAddVertex(way.id, node.id)
49982         );
49983
49984         context.enter(modeDrawArea(context, way.id, graph));
49985     }
49986
49987
49988     function startFromWay(loc, edge) {
49989         var graph = context.graph(),
49990             node = osmNode({ loc: loc }),
49991             way = osmWay({ tags: defaultTags });
49992
49993         context.perform(
49994             actionAddEntity(node),
49995             actionAddEntity(way),
49996             actionAddVertex(way.id, node.id),
49997             actionAddVertex(way.id, node.id),
49998             actionAddMidpoint({ loc: loc, edge: edge }, node)
49999         );
50000
50001         context.enter(modeDrawArea(context, way.id, graph));
50002     }
50003
50004
50005     function startFromNode(node) {
50006         var graph = context.graph(),
50007             way = osmWay({ tags: defaultTags });
50008
50009         context.perform(
50010             actionAddEntity(way),
50011             actionAddVertex(way.id, node.id),
50012             actionAddVertex(way.id, node.id)
50013         );
50014
50015         context.enter(modeDrawArea(context, way.id, graph));
50016     }
50017
50018
50019     mode.enter = function() {
50020         context.install(behavior);
50021     };
50022
50023
50024     mode.exit = function() {
50025         context.uninstall(behavior);
50026     };
50027
50028
50029     return mode;
50030 }
50031
50032 function modeAddLine$$1(context) {
50033     var mode = {
50034         id: 'add-line',
50035         button: 'line',
50036         title: t('modes.add_line.title'),
50037         description: t('modes.add_line.description'),
50038         key: '2'
50039     };
50040
50041     var behavior = behaviorAddWay(context)
50042         .tail(t('modes.add_line.tail'))
50043         .on('start', start)
50044         .on('startFromWay', startFromWay)
50045         .on('startFromNode', startFromNode);
50046
50047
50048     function start(loc) {
50049         var baseGraph = context.graph(),
50050             node = osmNode({ loc: loc }),
50051             way = osmWay();
50052
50053         context.perform(
50054             actionAddEntity(node),
50055             actionAddEntity(way),
50056             actionAddVertex(way.id, node.id)
50057         );
50058
50059         context.enter(modeDrawLine(context, way.id, baseGraph));
50060     }
50061
50062
50063     function startFromWay(loc, edge) {
50064         var baseGraph = context.graph(),
50065             node = osmNode({ loc: loc }),
50066             way = osmWay();
50067
50068         context.perform(
50069             actionAddEntity(node),
50070             actionAddEntity(way),
50071             actionAddVertex(way.id, node.id),
50072             actionAddMidpoint({ loc: loc, edge: edge }, node)
50073         );
50074
50075         context.enter(modeDrawLine(context, way.id, baseGraph));
50076     }
50077
50078
50079     function startFromNode(node) {
50080         var baseGraph = context.graph(),
50081             way = osmWay();
50082
50083         context.perform(
50084             actionAddEntity(way),
50085             actionAddVertex(way.id, node.id)
50086         );
50087
50088         context.enter(modeDrawLine(context, way.id, baseGraph));
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     return mode;
50102 }
50103
50104 function modeAddPoint$$1(context) {
50105     var mode = {
50106         id: 'add-point',
50107         button: 'point',
50108         title: t('modes.add_point.title'),
50109         description: t('modes.add_point.description'),
50110         key: '1'
50111     };
50112
50113     var behavior = behaviorDraw(context)
50114         .tail(t('modes.add_point.tail'))
50115         .on('click', add)
50116         .on('clickWay', addWay)
50117         .on('clickNode', addNode)
50118         .on('cancel', cancel)
50119         .on('finish', cancel);
50120
50121
50122     function add(loc) {
50123         var node = osmNode({ loc: loc });
50124
50125         context.perform(
50126             actionAddEntity(node),
50127             t('operations.add.annotation.point')
50128         );
50129
50130         context.enter(
50131             modeSelect(context, [node.id]).suppressMenu(true).newFeature(true)
50132         );
50133     }
50134
50135
50136     function addWay(loc) {
50137         add(loc);
50138     }
50139
50140
50141     function addNode(node) {
50142         add(node.loc);
50143     }
50144
50145
50146     function cancel() {
50147         context.enter(modeBrowse$$1(context));
50148     }
50149
50150
50151     mode.enter = function() {
50152         context.install(behavior);
50153     };
50154
50155
50156     mode.exit = function() {
50157         context.uninstall(behavior);
50158     };
50159
50160
50161     return mode;
50162 }
50163
50164 function modeBrowse$$1(context) {
50165     var mode = {
50166         button: 'browse',
50167         id: 'browse',
50168         title: t('modes.browse.title'),
50169         description: t('modes.browse.description')
50170     }, sidebar;
50171
50172     var behaviors = [
50173         behaviorPaste(context),
50174         behaviorHover(context).on('hover', context.ui().sidebar.hover),
50175         behaviorSelect(context),
50176         behaviorLasso(context),
50177         modeDragNode$$1(context).behavior
50178     ];
50179
50180
50181     mode.enter = function() {
50182         behaviors.forEach(function(behavior) {
50183             context.install(behavior);
50184         });
50185
50186         // Get focus on the body.
50187         if (document.activeElement && document.activeElement.blur) {
50188             document.activeElement.blur();
50189         }
50190
50191         if (sidebar) {
50192             context.ui().sidebar.show(sidebar);
50193         } else {
50194             context.ui().sidebar.select(null);
50195         }
50196     };
50197
50198
50199     mode.exit = function() {
50200         context.ui().sidebar.hover.cancel();
50201         behaviors.forEach(function(behavior) {
50202             context.uninstall(behavior);
50203         });
50204
50205         if (sidebar) {
50206             context.ui().sidebar.hide();
50207         }
50208     };
50209
50210
50211     mode.sidebar = function(_) {
50212         if (!arguments.length) return sidebar;
50213         sidebar = _;
50214         return mode;
50215     };
50216
50217
50218     return mode;
50219 }
50220
50221 function modeDragNode$$1(context) {
50222     var mode = {
50223         id: 'drag-node',
50224         button: 'browse'
50225     };
50226
50227     var nudgeInterval,
50228         activeIDs,
50229         wasMidpoint,
50230         isCancelled,
50231         selectedIDs = [],
50232         hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
50233         edit = behaviorEdit(context);
50234
50235
50236     function edge(point, size) {
50237         var pad = [30, 100, 30, 100];
50238         if (point[0] > size[0] - pad[0]) return [-10, 0];
50239         else if (point[0] < pad[2]) return [10, 0];
50240         else if (point[1] > size[1] - pad[1]) return [0, -10];
50241         else if (point[1] < pad[3]) return [0, 10];
50242         return null;
50243     }
50244
50245
50246     function startNudge(nudge) {
50247         if (nudgeInterval) window.clearInterval(nudgeInterval);
50248         nudgeInterval = window.setInterval(function() {
50249             context.pan(nudge);
50250         }, 50);
50251     }
50252
50253
50254     function stopNudge() {
50255         if (nudgeInterval) window.clearInterval(nudgeInterval);
50256         nudgeInterval = null;
50257     }
50258
50259
50260     function moveAnnotation(entity) {
50261         return t('operations.move.annotation.' + entity.geometry(context.graph()));
50262     }
50263
50264
50265     function connectAnnotation(entity) {
50266         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
50267     }
50268
50269
50270     function origin(entity) {
50271         return context.projection(entity.loc);
50272     }
50273
50274
50275     function start(entity) {
50276         isCancelled = event.sourceEvent.shiftKey ||
50277             context.features().hasHiddenConnections(entity, context.graph());
50278
50279         if (isCancelled) return behavior.cancel();
50280
50281         wasMidpoint = entity.type === 'midpoint';
50282         if (wasMidpoint) {
50283             var midpoint = entity;
50284             entity = osmNode();
50285             context.perform(actionAddMidpoint(midpoint, entity));
50286
50287             var vertex = context.surface().selectAll('.' + entity.id);
50288             behavior.target(vertex.node(), entity);
50289
50290         } else {
50291             context.perform(actionNoop());
50292         }
50293
50294         activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
50295         activeIDs.push(entity.id);
50296         context.enter(mode);
50297     }
50298
50299
50300     function datum() {
50301         if (event.sourceEvent.altKey) {
50302             return {};
50303         }
50304
50305         return event.sourceEvent.target.__data__ || {};
50306     }
50307
50308
50309     // via https://gist.github.com/shawnbot/4166283
50310     function childOf(p, c) {
50311         if (p === c) return false;
50312         while (c && c !== p) c = c.parentNode;
50313         return c === p;
50314     }
50315
50316
50317     function move(entity) {
50318         if (isCancelled) return;
50319         event.sourceEvent.stopPropagation();
50320
50321         var nudge = childOf(context.container().node(),
50322             event.sourceEvent.toElement) &&
50323             edge(event.point, context.map().dimensions());
50324
50325         if (nudge) startNudge(nudge);
50326         else stopNudge();
50327
50328         var loc = context.projection.invert(event.point);
50329
50330         var d = datum();
50331         if (d.type === 'node' && d.id !== entity.id) {
50332             loc = d.loc;
50333         } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
50334             loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
50335         }
50336
50337         context.replace(
50338             actionMoveNode(entity.id, loc),
50339             moveAnnotation(entity)
50340         );
50341     }
50342
50343
50344     function end(entity) {
50345         if (isCancelled) return;
50346
50347         var d = datum();
50348
50349         if (d.type === 'way') {
50350             var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
50351             context.replace(
50352                 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
50353                 connectAnnotation(d)
50354             );
50355
50356         } else if (d.type === 'node' && d.id !== entity.id) {
50357             context.replace(
50358                 actionConnect([d.id, entity.id]),
50359                 connectAnnotation(d)
50360             );
50361
50362         } else if (wasMidpoint) {
50363             context.replace(
50364                 actionNoop(),
50365                 t('operations.add.annotation.vertex')
50366             );
50367
50368         } else {
50369             context.replace(
50370                 actionNoop(),
50371                 moveAnnotation(entity)
50372             );
50373         }
50374
50375         var reselection = selectedIDs.filter(function(id) {
50376             return context.graph().hasEntity(id);
50377         });
50378
50379         if (reselection.length) {
50380             context.enter(modeSelect(context, reselection).suppressMenu(true));
50381         } else {
50382             context.enter(modeBrowse$$1(context));
50383         }
50384     }
50385
50386
50387     function cancel() {
50388         behavior.cancel();
50389         context.enter(modeBrowse$$1(context));
50390     }
50391
50392
50393     function setActiveElements() {
50394         context.surface().selectAll(utilEntitySelector(activeIDs))
50395             .classed('active', true);
50396     }
50397
50398
50399     var behavior = behaviorDrag()
50400         .delegate('g.node, g.point, g.midpoint')
50401         .surface(context.surface().node())
50402         .origin(origin)
50403         .on('start', start)
50404         .on('move', move)
50405         .on('end', end);
50406
50407
50408     mode.enter = function() {
50409         context.install(hover);
50410         context.install(edit);
50411
50412         context.history()
50413             .on('undone.drag-node', cancel);
50414
50415         context.map()
50416             .on('drawn.drag-node', setActiveElements);
50417
50418         setActiveElements();
50419     };
50420
50421
50422     mode.exit = function() {
50423         context.ui().sidebar.hover.cancel();
50424         context.uninstall(hover);
50425         context.uninstall(edit);
50426
50427         context.history()
50428             .on('undone.drag-node', null);
50429
50430         context.map()
50431             .on('drawn.drag-node', null);
50432
50433         context.surface()
50434             .selectAll('.active')
50435             .classed('active', false);
50436
50437         stopNudge();
50438     };
50439
50440
50441     mode.selectedIDs = function(_) {
50442         if (!arguments.length) return selectedIDs;
50443         selectedIDs = _;
50444         return mode;
50445     };
50446
50447
50448     mode.behavior = behavior;
50449
50450
50451     return mode;
50452 }
50453
50454 function modeDrawArea(context, wayId, baseGraph) {
50455     var mode = {
50456         button: 'area',
50457         id: 'draw-area'
50458     };
50459
50460     var behavior;
50461
50462
50463     mode.enter = function() {
50464         var way = context.entity(wayId),
50465             headId = way.nodes[way.nodes.length - 2],
50466             tailId = way.first();
50467
50468         behavior = behaviorDrawWay(context, wayId, -1, mode, baseGraph)
50469             .tail(t('modes.draw_area.tail'));
50470
50471         var addNode = behavior.addNode;
50472
50473         behavior.addNode = function(node) {
50474             if (node.id === headId || node.id === tailId) {
50475                 behavior.finish();
50476             } else {
50477                 addNode(node);
50478             }
50479         };
50480
50481         context.install(behavior);
50482     };
50483
50484
50485     mode.exit = function() {
50486         context.uninstall(behavior);
50487     };
50488
50489
50490     mode.selectedIDs = function() {
50491         return [wayId];
50492     };
50493
50494
50495     return mode;
50496 }
50497
50498 function modeDrawLine(context, wayId, baseGraph, affix) {
50499     var mode = {
50500         button: 'line',
50501         id: 'draw-line'
50502     };
50503
50504     var behavior;
50505
50506
50507     mode.enter = function() {
50508         var way = context.entity(wayId),
50509             index = (affix === 'prefix') ? 0 : undefined,
50510             headId = (affix === 'prefix') ? way.first() : way.last();
50511
50512         behavior = behaviorDrawWay(context, wayId, index, mode, baseGraph)
50513             .tail(t('modes.draw_line.tail'));
50514
50515         var addNode = behavior.addNode;
50516
50517         behavior.addNode = function(node) {
50518             if (node.id === headId) {
50519                 behavior.finish();
50520             } else {
50521                 addNode(node);
50522             }
50523         };
50524
50525         context.install(behavior);
50526     };
50527
50528
50529     mode.exit = function() {
50530         context.uninstall(behavior);
50531     };
50532
50533
50534     mode.selectedIDs = function() {
50535         return [wayId];
50536     };
50537
50538
50539     return mode;
50540 }
50541
50542 function modeMove$$1(context, entityIDs, baseGraph) {
50543     var mode = {
50544         id: 'move',
50545         button: 'browse'
50546     };
50547
50548     var keybinding = d3keybinding('move'),
50549         edit = behaviorEdit(context),
50550         annotation = entityIDs.length === 1 ?
50551             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
50552             t('operations.move.annotation.multiple'),
50553         cache,
50554         origin,
50555         nudgeInterval;
50556
50557
50558     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
50559
50560
50561     function edge(point, size) {
50562         var pad = [30, 100, 30, 100];
50563         if (point[0] > size[0] - pad[0]) return [-10, 0];
50564         else if (point[0] < pad[2]) return [10, 0];
50565         else if (point[1] > size[1] - pad[1]) return [0, -10];
50566         else if (point[1] < pad[3]) return [0, 10];
50567         return null;
50568     }
50569
50570
50571     function startNudge(nudge) {
50572         if (nudgeInterval) window.clearInterval(nudgeInterval);
50573         nudgeInterval = window.setInterval(function() {
50574             context.pan(nudge);
50575
50576             var currMouse = context.mouse(),
50577                 origMouse = context.projection(origin),
50578                 delta = vecSub(vecSub(currMouse, origMouse), nudge),
50579                 action = actionMove(entityIDs, delta, context.projection, cache);
50580
50581             context.overwrite(action, annotation);
50582
50583         }, 50);
50584     }
50585
50586
50587     function stopNudge() {
50588         if (nudgeInterval) window.clearInterval(nudgeInterval);
50589         nudgeInterval = null;
50590     }
50591
50592
50593     function move() {
50594         var currMouse = context.mouse(),
50595             origMouse = context.projection(origin),
50596             delta = vecSub(currMouse, origMouse),
50597             action = actionMove(entityIDs, delta, context.projection, cache);
50598
50599         context.overwrite(action, annotation);
50600
50601         var nudge = edge(currMouse, context.map().dimensions());
50602         if (nudge) startNudge(nudge);
50603         else stopNudge();
50604     }
50605
50606
50607     function finish() {
50608         event.stopPropagation();
50609         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
50610         stopNudge();
50611     }
50612
50613
50614     function cancel() {
50615         if (baseGraph) {
50616             while (context.graph() !== baseGraph) context.pop();
50617             context.enter(modeBrowse$$1(context));
50618         } else {
50619             context.pop();
50620             context.enter(modeSelect(context, entityIDs).suppressMenu(true));
50621         }
50622         stopNudge();
50623     }
50624
50625
50626     function undone() {
50627         context.enter(modeBrowse$$1(context));
50628     }
50629
50630
50631     mode.enter = function() {
50632         origin = context.map().mouseCoordinates();
50633         cache = {};
50634
50635         context.install(edit);
50636
50637         context.perform(
50638             actionNoop(),
50639             annotation
50640         );
50641
50642         context.surface()
50643             .on('mousemove.move', move)
50644             .on('click.move', finish);
50645
50646         context.history()
50647             .on('undone.move', undone);
50648
50649         keybinding
50650             .on('⎋', cancel)
50651             .on('↩', finish);
50652
50653         select(document)
50654             .call(keybinding);
50655     };
50656
50657
50658     mode.exit = function() {
50659         stopNudge();
50660
50661         context.uninstall(edit);
50662
50663         context.surface()
50664             .on('mousemove.move', null)
50665             .on('click.move', null);
50666
50667         context.history()
50668             .on('undone.move', null);
50669
50670         keybinding.off();
50671     };
50672
50673
50674     return mode;
50675 }
50676
50677 function modeRotateWay$$1(context, wayId) {
50678     var mode = {
50679         id: 'rotate-way',
50680         button: 'browse'
50681     };
50682
50683     var keybinding = d3keybinding('rotate-way'),
50684         edit = behaviorEdit(context);
50685
50686
50687     mode.enter = function() {
50688         context.install(edit);
50689
50690         var annotation = t('operations.rotate.annotation.' + context.geometry(wayId)),
50691             way = context.graph().entity(wayId),
50692             nodes = lodash.uniq(context.graph().childNodes(way)),
50693             points = nodes.map(function(n) { return context.projection(n.loc); }),
50694             pivot = d3polygonCentroid(points),
50695             angle;
50696
50697         context.perform(
50698             actionNoop(),
50699             annotation
50700         );
50701
50702         context.surface()
50703             .on('mousemove.rotate-way', rotate)
50704             .on('click.rotate-way', finish);
50705
50706         context.history()
50707             .on('undone.rotate-way', undone);
50708
50709         keybinding
50710             .on('⎋', cancel)
50711             .on('↩', finish);
50712
50713         select(document)
50714             .call(keybinding);
50715
50716
50717         function rotate() {
50718             var mousePoint = context.mouse(),
50719                 newAngle = Math.atan2(mousePoint[1] - pivot[1], mousePoint[0] - pivot[0]);
50720
50721             if (typeof angle === 'undefined') angle = newAngle;
50722
50723             context.replace(
50724                 actionRotateWay(wayId, pivot, newAngle - angle, context.projection),
50725                 annotation
50726             );
50727
50728             angle = newAngle;
50729         }
50730
50731
50732         function finish() {
50733             event.stopPropagation();
50734             context.enter(modeSelect(context, [wayId]).suppressMenu(true));
50735         }
50736
50737
50738         function cancel() {
50739             context.pop();
50740             context.enter(modeSelect(context, [wayId]).suppressMenu(true));
50741         }
50742
50743
50744         function undone() {
50745             context.enter(modeBrowse$$1(context));
50746         }
50747     };
50748
50749
50750     mode.exit = function() {
50751         context.uninstall(edit);
50752
50753         context.surface()
50754             .on('mousemove.rotate-way', null)
50755             .on('click.rotate-way', null);
50756
50757         context.history()
50758             .on('undone.rotate-way', null);
50759
50760         keybinding.off();
50761     };
50762
50763
50764     return mode;
50765 }
50766
50767 function modeSave$$1(context) {
50768     var mode = {
50769         id: 'save'
50770     };
50771
50772     var ui = uiCommit(context)
50773             .on('cancel', cancel)
50774             .on('save', save);
50775
50776
50777     function cancel() {
50778         context.enter(modeBrowse$$1(context));
50779     }
50780
50781
50782     function save(e, tryAgain) {
50783         function withChildNodes(ids, graph) {
50784             return lodash.uniq(lodash.reduce(ids, function(result, id) {
50785                 var e = graph.entity(id);
50786                 if (e.type === 'way') {
50787                     try {
50788                         var cn = graph.childNodes(e);
50789                         result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
50790                     } catch (err) {
50791                         /* eslint-disable no-console */
50792                         if (typeof console !== 'undefined') console.error(err);
50793                         /* eslint-enable no-console */
50794                     }
50795                 }
50796                 return result;
50797             }, lodash.clone(ids)));
50798         }
50799
50800         var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
50801             history = context.history(),
50802             origChanges = history.changes(actionDiscardTags(history.difference())),
50803             localGraph = context.graph(),
50804             remoteGraph = coreGraph$$1(history.base(), true),
50805             modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
50806             toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
50807             toLoad = withChildNodes(toCheck, localGraph),
50808             conflicts = [],
50809             errors = [];
50810
50811         if (!tryAgain) history.perform(actionNoop());  // checkpoint
50812         context.container().call(loading);
50813
50814         if (toCheck.length) {
50815             context.connection().loadMultiple(toLoad, loaded);
50816         } else {
50817             finalize();
50818         }
50819
50820
50821         // Reload modified entities into an alternate graph and check for conflicts..
50822         function loaded(err, result) {
50823             if (errors.length) return;
50824
50825             if (err) {
50826                 errors.push({
50827                     msg: err.responseText,
50828                     details: [ t('save.status_code', { code: err.status }) ]
50829                 });
50830                 showErrors();
50831
50832             } else {
50833                 var loadMore = [];
50834                 lodash.each(result.data, function(entity) {
50835                     remoteGraph.replace(entity);
50836                     toLoad = lodash.without(toLoad, entity.id);
50837
50838                     // Because loadMultiple doesn't download /full like loadEntity,
50839                     // need to also load children that aren't already being checked..
50840                     if (!entity.visible) return;
50841                     if (entity.type === 'way') {
50842                         loadMore.push.apply(loadMore,
50843                             lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
50844                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
50845                         loadMore.push.apply(loadMore,
50846                             lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
50847                     }
50848                 });
50849
50850                 if (loadMore.length) {
50851                     toLoad.push.apply(toLoad, loadMore);
50852                     context.connection().loadMultiple(loadMore, loaded);
50853                 }
50854
50855                 if (!toLoad.length) {
50856                     checkConflicts();
50857                 }
50858             }
50859         }
50860
50861
50862         function checkConflicts() {
50863             function choice(id, text$$1, action) {
50864                 return { id: id, text: text$$1, action: function() { history.replace(action); } };
50865             }
50866             function formatUser(d) {
50867                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
50868             }
50869             function entityName(entity) {
50870                 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
50871             }
50872
50873             function compareVersions(local$$1, remote) {
50874                 if (local$$1.version !== remote.version) return false;
50875
50876                 if (local$$1.type === 'way') {
50877                     var children = lodash.union(local$$1.nodes, remote.nodes);
50878
50879                     for (var i = 0; i < children.length; i++) {
50880                         var a = localGraph.hasEntity(children[i]),
50881                             b = remoteGraph.hasEntity(children[i]);
50882
50883                         if (a && b && a.version !== b.version) return false;
50884                     }
50885                 }
50886
50887                 return true;
50888             }
50889
50890             lodash.each(toCheck, function(id) {
50891                 var local$$1 = localGraph.entity(id),
50892                     remote = remoteGraph.entity(id);
50893
50894                 if (compareVersions(local$$1, remote)) return;
50895
50896                 var action = actionMergeRemoteChanges,
50897                     merge$$1 = action(id, localGraph, remoteGraph, formatUser);
50898
50899                 history.replace(merge$$1);
50900
50901                 var mergeConflicts = merge$$1.conflicts();
50902                 if (!mergeConflicts.length) return;  // merged safely
50903
50904                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
50905                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
50906                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
50907                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
50908
50909                 conflicts.push({
50910                     id: id,
50911                     name: entityName(local$$1),
50912                     details: mergeConflicts,
50913                     chosen: 1,
50914                     choices: [
50915                         choice(id, keepMine, forceLocal),
50916                         choice(id, keepTheirs, forceRemote)
50917                     ]
50918                 });
50919             });
50920
50921             finalize();
50922         }
50923
50924
50925         function finalize() {
50926             if (conflicts.length) {
50927                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
50928                 showConflicts();
50929             } else if (errors.length) {
50930                 showErrors();
50931             } else {
50932                 var changes = history.changes(actionDiscardTags(history.difference()));
50933                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
50934                     context.connection().putChangeset(
50935                         changes,
50936                         context.version,
50937                         e.comment,
50938                         history.imageryUsed(),
50939                         function(err, changeset_id) {
50940                             if (err) {
50941                                 errors.push({
50942                                     msg: err.responseText,
50943                                     details: [ t('save.status_code', { code: err.status }) ]
50944                                 });
50945                                 showErrors();
50946                             } else {
50947                                 history.clearSaved();
50948                                 success(e, changeset_id);
50949                                 // Add delay to allow for postgres replication #1646 #2678
50950                                 window.setTimeout(function() {
50951                                     loading.close();
50952                                     context.flush();
50953                                 }, 2500);
50954                             }
50955                         });
50956                 } else {        // changes were insignificant or reverted by user
50957                     loading.close();
50958                     context.flush();
50959                     cancel();
50960                 }
50961             }
50962         }
50963
50964
50965         function showConflicts() {
50966             var selection$$1 = context.container()
50967                 .select('#sidebar')
50968                 .append('div')
50969                 .attr('class','sidebar-component');
50970
50971             loading.close();
50972
50973             selection$$1.call(uiConflicts(context)
50974                 .list(conflicts)
50975                 .on('download', function() {
50976                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
50977                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
50978                     win.focus();
50979                 })
50980                 .on('cancel', function() {
50981                     history.pop();
50982                     selection$$1.remove();
50983                 })
50984                 .on('save', function() {
50985                     for (var i = 0; i < conflicts.length; i++) {
50986                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
50987                             var entity = context.hasEntity(conflicts[i].id);
50988                             if (entity && entity.type === 'way') {
50989                                 var children = lodash.uniq(entity.nodes);
50990                                 for (var j = 0; j < children.length; j++) {
50991                                     history.replace(actionRevert(children[j]));
50992                                 }
50993                             }
50994                             history.replace(actionRevert(conflicts[i].id));
50995                         }
50996                     }
50997
50998                     selection$$1.remove();
50999                     save(e, true);
51000                 })
51001             );
51002         }
51003
51004
51005         function showErrors() {
51006             var selection$$1 = uiConfirm(context.container());
51007
51008             history.pop();
51009             loading.close();
51010
51011             selection$$1
51012                 .select('.modal-section.header')
51013                 .append('h3')
51014                 .text(t('save.error'));
51015
51016             addErrors(selection$$1, errors);
51017             selection$$1.okButton();
51018         }
51019
51020
51021         function addErrors(selection$$1, data) {
51022             var message = selection$$1
51023                 .select('.modal-section.message-text');
51024
51025             var items = message
51026                 .selectAll('.error-container')
51027                 .data(data);
51028
51029             var enter = items.enter()
51030                 .append('div')
51031                 .attr('class', 'error-container');
51032
51033             enter
51034                 .append('a')
51035                 .attr('class', 'error-description')
51036                 .attr('href', '#')
51037                 .classed('hide-toggle', true)
51038                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
51039                 .on('click', function() {
51040                     var error = select(this),
51041                         detail = select(this.nextElementSibling),
51042                         exp = error.classed('expanded');
51043
51044                     detail.style('display', exp ? 'none' : 'block');
51045                     error.classed('expanded', !exp);
51046
51047                     event.preventDefault();
51048                 });
51049
51050             var details = enter
51051                 .append('div')
51052                 .attr('class', 'error-detail-container')
51053                 .style('display', 'none');
51054
51055             details
51056                 .append('ul')
51057                 .attr('class', 'error-detail-list')
51058                 .selectAll('li')
51059                 .data(function(d) { return d.details || []; })
51060                 .enter()
51061                 .append('li')
51062                 .attr('class', 'error-detail-item')
51063                 .text(function(d) { return d; });
51064
51065             items.exit()
51066                 .remove();
51067         }
51068
51069     }
51070
51071
51072     function success(e, changeset_id) {
51073         context.enter(modeBrowse$$1(context)
51074             .sidebar(uiSuccess(context)
51075                 .changeset({
51076                     id: changeset_id,
51077                     comment: e.comment
51078                 })
51079                 .on('cancel', function() {
51080                     context.ui().sidebar.hide();
51081                 })
51082             )
51083         );
51084     }
51085
51086
51087     mode.enter = function() {
51088         context.connection().authenticate(function(err) {
51089             if (err) {
51090                 cancel();
51091             } else {
51092                 context.ui().sidebar.show(ui);
51093             }
51094         });
51095     };
51096
51097
51098     mode.exit = function() {
51099         context.ui().sidebar.hide();
51100     };
51101
51102     return mode;
51103 }
51104
51105 function operationCircularize(selectedIDs, context) {
51106     var entityId = selectedIDs[0],
51107         entity = context.entity(entityId),
51108         extent = entity.extent(context.graph()),
51109         geometry = context.geometry(entityId),
51110         action = actionCircularize(entityId, context.projection);
51111
51112     var operation = function() {
51113         var annotation = t('operations.circularize.annotation.' + geometry);
51114         context.perform(action, annotation);
51115     };
51116
51117
51118     operation.available = function() {
51119         return selectedIDs.length === 1 &&
51120             entity.type === 'way' &&
51121             lodash.uniq(entity.nodes).length > 1;
51122     };
51123
51124
51125     operation.disabled = function() {
51126         var reason;
51127         if (extent.percentContainedIn(context.extent()) < 0.8) {
51128             reason = 'too_large';
51129         } else if (context.hasHiddenConnections(entityId)) {
51130             reason = 'connected_to_hidden';
51131         }
51132         return action.disabled(context.graph()) || reason;
51133     };
51134
51135
51136     operation.tooltip = function() {
51137         var disable = operation.disabled();
51138         return disable ?
51139             t('operations.circularize.' + disable) :
51140             t('operations.circularize.description.' + geometry);
51141     };
51142
51143
51144     operation.id = 'circularize';
51145     operation.keys = [t('operations.circularize.key')];
51146     operation.title = t('operations.circularize.title');
51147
51148
51149     return operation;
51150 }
51151
51152 function operationContinue(selectedIDs, context) {
51153     var graph = context.graph(),
51154         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51155         geometries = lodash.extend({ line: [], vertex: [] },
51156             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51157         vertex = geometries.vertex[0];
51158
51159
51160     function candidateWays() {
51161         return graph.parentWays(vertex).filter(function(parent) {
51162             return parent.geometry(graph) === 'line' &&
51163                 parent.affix(vertex.id) &&
51164                 (geometries.line.length === 0 || geometries.line[0] === parent);
51165         });
51166     }
51167
51168
51169     var operation = function() {
51170         var candidate = candidateWays()[0];
51171         context.enter(
51172             modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51173         );
51174     };
51175
51176
51177     operation.available = function() {
51178         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51179             !context.features().hasHiddenConnections(vertex, context.graph());
51180     };
51181
51182
51183     operation.disabled = function() {
51184         var candidates = candidateWays();
51185         if (candidates.length === 0)
51186             return 'not_eligible';
51187         if (candidates.length > 1)
51188             return 'multiple';
51189     };
51190
51191
51192     operation.tooltip = function() {
51193         var disable = operation.disabled();
51194         return disable ?
51195             t('operations.continue.' + disable) :
51196             t('operations.continue.description');
51197     };
51198
51199
51200     operation.id = 'continue';
51201     operation.keys = [t('operations.continue.key')];
51202     operation.title = t('operations.continue.title');
51203
51204
51205     return operation;
51206 }
51207
51208 function operationDelete(selectedIDs, context) {
51209     var action = actionDeleteMultiple(selectedIDs);
51210
51211     var operation = function() {
51212         var annotation,
51213             nextSelectedID;
51214
51215         if (selectedIDs.length > 1) {
51216             annotation = t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51217
51218         } else {
51219             var id = selectedIDs[0],
51220                 entity = context.entity(id),
51221                 geometry = context.geometry(id),
51222                 parents = context.graph().parentWays(entity),
51223                 parent = parents[0];
51224
51225             annotation = t('operations.delete.annotation.' + geometry);
51226
51227             // Select the next closest node in the way.
51228             if (geometry === 'vertex' && parent.nodes.length > 2) {
51229                 var nodes = parent.nodes,
51230                     i = nodes.indexOf(id);
51231
51232                 if (i === 0) {
51233                     i++;
51234                 } else if (i === nodes.length - 1) {
51235                     i--;
51236                 } else {
51237                     var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51238                         b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51239                     i = a < b ? i - 1 : i + 1;
51240                 }
51241
51242                 nextSelectedID = nodes[i];
51243             }
51244         }
51245
51246         context.perform(action, annotation);
51247
51248         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51249             context.enter(
51250                 modeSelect(context, [nextSelectedID]).follow(true).suppressMenu(true)
51251             );
51252         } else {
51253             context.enter(modeBrowse$$1(context));
51254         }
51255
51256     };
51257
51258
51259     operation.available = function() {
51260         return true;
51261     };
51262
51263
51264     operation.disabled = function() {
51265         var reason;
51266         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51267             reason = 'connected_to_hidden';
51268         }
51269         return action.disabled(context.graph()) || reason;
51270     };
51271
51272
51273     operation.tooltip = function() {
51274         var disable = operation.disabled();
51275         return disable ?
51276             t('operations.delete.' + disable) :
51277             t('operations.delete.description');
51278     };
51279
51280
51281     operation.id = 'delete';
51282     operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51283     operation.title = t('operations.delete.title');
51284
51285
51286     return operation;
51287 }
51288
51289 function operationDisconnect(selectedIDs, context) {
51290     var vertices = lodash.filter(selectedIDs, function(entityId) {
51291         return context.geometry(entityId) === 'vertex';
51292     });
51293
51294     var entityId = vertices[0],
51295         action = actionDisconnect(entityId);
51296
51297     if (selectedIDs.length > 1) {
51298         action.limitWays(lodash.without(selectedIDs, entityId));
51299     }
51300
51301     var operation = function() {
51302         context.perform(action, t('operations.disconnect.annotation'));
51303     };
51304
51305
51306     operation.available = function() {
51307         return vertices.length === 1;
51308     };
51309
51310
51311     operation.disabled = function() {
51312         var reason;
51313         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51314             reason = 'connected_to_hidden';
51315         }
51316         return action.disabled(context.graph()) || reason;
51317     };
51318
51319
51320     operation.tooltip = function() {
51321         var disable = operation.disabled();
51322         return disable ?
51323             t('operations.disconnect.' + disable) :
51324             t('operations.disconnect.description');
51325     };
51326
51327
51328     operation.id = 'disconnect';
51329     operation.keys = [t('operations.disconnect.key')];
51330     operation.title = t('operations.disconnect.title');
51331
51332
51333     return operation;
51334 }
51335
51336 function operationMerge(selectedIDs, context) {
51337     var join = actionJoin(selectedIDs),
51338         merge = actionMerge(selectedIDs),
51339         mergePolygon = actionMergePolygon(selectedIDs);
51340
51341     var operation = function() {
51342         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
51343             action;
51344
51345         if (!join.disabled(context.graph())) {
51346             action = join;
51347         } else if (!merge.disabled(context.graph())) {
51348             action = merge;
51349         } else {
51350             action = mergePolygon;
51351         }
51352
51353         context.perform(action, annotation);
51354         var ids = selectedIDs.filter(function(id) { return context.hasEntity(id); });
51355         context.enter(modeSelect(context, ids).suppressMenu(true));
51356     };
51357
51358
51359     operation.available = function() {
51360         return selectedIDs.length >= 2;
51361     };
51362
51363
51364     operation.disabled = function() {
51365         return join.disabled(context.graph()) &&
51366             merge.disabled(context.graph()) &&
51367             mergePolygon.disabled(context.graph());
51368     };
51369
51370
51371     operation.tooltip = function() {
51372         var j = join.disabled(context.graph()),
51373             m = merge.disabled(context.graph()),
51374             p = mergePolygon.disabled(context.graph());
51375
51376         if (j === 'restriction' && m && p) {
51377             return t('operations.merge.restriction',
51378                 { relation: context.presets().item('type/restriction').name() });
51379         }
51380
51381         if (p === 'incomplete_relation' && j && m) {
51382             return t('operations.merge.incomplete_relation');
51383         }
51384
51385         if (j && m && p) {
51386             return t('operations.merge.' + j);
51387         }
51388
51389         return t('operations.merge.description');
51390     };
51391
51392
51393     operation.id = 'merge';
51394     operation.keys = [t('operations.merge.key')];
51395     operation.title = t('operations.merge.title');
51396
51397
51398     return operation;
51399 }
51400
51401 function operationMove(selectedIDs, context) {
51402     var extent = selectedIDs.reduce(function(extent, id) {
51403             return extent.extend(context.entity(id).extent(context.graph()));
51404         }, geoExtent$$1());
51405
51406     var operation = function() {
51407         context.enter(modeMove$$1(context, selectedIDs));
51408     };
51409
51410
51411     operation.available = function() {
51412         return selectedIDs.length > 1 ||
51413             context.entity(selectedIDs[0]).type !== 'node';
51414     };
51415
51416
51417     operation.disabled = function() {
51418         var reason;
51419         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51420             reason = 'too_large';
51421         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51422             reason = 'connected_to_hidden';
51423         }
51424
51425         return actionMove(selectedIDs).disabled(context.graph()) || reason;
51426     };
51427
51428
51429     operation.tooltip = function() {
51430         var disable = operation.disabled();
51431         return disable ?
51432             t('operations.move.' + disable) :
51433             t('operations.move.description');
51434     };
51435
51436
51437     operation.id = 'move';
51438     operation.keys = [t('operations.move.key')];
51439     operation.title = t('operations.move.title');
51440
51441
51442     return operation;
51443 }
51444
51445 function operationOrthogonalize(selectedIDs, context) {
51446     var entityId = selectedIDs[0],
51447         entity = context.entity(entityId),
51448         extent = entity.extent(context.graph()),
51449         geometry = context.geometry(entityId),
51450         action = actionOrthogonalize(entityId, context.projection);
51451
51452     var operation = function() {
51453         var annotation = t('operations.orthogonalize.annotation.' + geometry);
51454         context.perform(action, annotation);
51455     };
51456
51457
51458     operation.available = function() {
51459         return selectedIDs.length === 1 &&
51460             entity.type === 'way' &&
51461             entity.isClosed() &&
51462             lodash.uniq(entity.nodes).length > 2;
51463     };
51464
51465
51466     operation.disabled = function() {
51467         var reason;
51468         if (extent.percentContainedIn(context.extent()) < 0.8) {
51469             reason = 'too_large';
51470         } else if (context.hasHiddenConnections(entityId)) {
51471             reason = 'connected_to_hidden';
51472         }
51473         return action.disabled(context.graph()) || reason;
51474     };
51475
51476
51477     operation.tooltip = function() {
51478         var disable = operation.disabled();
51479         return disable ?
51480             t('operations.orthogonalize.' + disable) :
51481             t('operations.orthogonalize.description.' + geometry);
51482     };
51483
51484
51485     operation.id = 'orthogonalize';
51486     operation.keys = [t('operations.orthogonalize.key')];
51487     operation.title = t('operations.orthogonalize.title');
51488
51489
51490     return operation;
51491 }
51492
51493 function operationReverse(selectedIDs, context) {
51494     var entityId = selectedIDs[0];
51495
51496     var operation = function() {
51497         context.perform(
51498             actionReverse(entityId),
51499             t('operations.reverse.annotation')
51500         );
51501     };
51502
51503
51504     operation.available = function() {
51505         return selectedIDs.length === 1 &&
51506             context.geometry(entityId) === 'line';
51507     };
51508
51509
51510     operation.disabled = function() {
51511         return false;
51512     };
51513
51514
51515     operation.tooltip = function() {
51516         return t('operations.reverse.description');
51517     };
51518
51519
51520     operation.id = 'reverse';
51521     operation.keys = [t('operations.reverse.key')];
51522     operation.title = t('operations.reverse.title');
51523
51524
51525     return operation;
51526 }
51527
51528 function operationRotate(selectedIDs, context) {
51529     var entityId = selectedIDs[0],
51530         entity = context.entity(entityId),
51531         extent = entity.extent(context.graph()),
51532         geometry = context.geometry(entityId);
51533
51534     var operation = function() {
51535         context.enter(modeRotateWay$$1(context, entityId));
51536     };
51537
51538
51539     operation.available = function() {
51540         if (selectedIDs.length !== 1 || entity.type !== 'way')
51541             return false;
51542         if (geometry === 'area')
51543             return true;
51544         if (entity.isClosed() &&
51545             context.graph().parentRelations(entity).some(function(r) { return r.isMultipolygon(); }))
51546             return true;
51547         return false;
51548     };
51549
51550
51551     operation.disabled = function() {
51552         if (extent.percentContainedIn(context.extent()) < 0.8) {
51553             return 'too_large';
51554         } else if (context.hasHiddenConnections(entityId)) {
51555             return 'connected_to_hidden';
51556         } else {
51557             return false;
51558         }
51559     };
51560
51561
51562     operation.tooltip = function() {
51563         var disable = operation.disabled();
51564         return disable ?
51565             t('operations.rotate.' + disable) :
51566             t('operations.rotate.description');
51567     };
51568
51569
51570     operation.id = 'rotate';
51571     operation.keys = [t('operations.rotate.key')];
51572     operation.title = t('operations.rotate.title');
51573
51574
51575     return operation;
51576 }
51577
51578 function operationSplit(selectedIDs, context) {
51579     var vertices = lodash.filter(selectedIDs, function(entityId) {
51580         return context.geometry(entityId) === 'vertex';
51581     });
51582
51583     var entityId = vertices[0],
51584         action = actionSplit(entityId);
51585
51586     if (selectedIDs.length > 1) {
51587         action.limitWays(lodash.without(selectedIDs, entityId));
51588     }
51589
51590
51591     var operation = function() {
51592         var annotation;
51593
51594         var ways = action.ways(context.graph());
51595         if (ways.length === 1) {
51596             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
51597         } else {
51598             annotation = t('operations.split.annotation.multiple', {n: ways.length});
51599         }
51600
51601         var difference = context.perform(action, annotation);
51602         context.enter(modeSelect(context, difference.extantIDs()));
51603     };
51604
51605
51606     operation.available = function() {
51607         return vertices.length === 1;
51608     };
51609
51610
51611     operation.disabled = function() {
51612         var reason;
51613         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51614             reason = 'connected_to_hidden';
51615         }
51616         return action.disabled(context.graph()) || reason;
51617     };
51618
51619
51620     operation.tooltip = function() {
51621         var disable = operation.disabled();
51622         if (disable) {
51623             return t('operations.split.' + disable);
51624         }
51625
51626         var ways = action.ways(context.graph());
51627         if (ways.length === 1) {
51628             return t('operations.split.description.' + context.geometry(ways[0].id));
51629         } else {
51630             return t('operations.split.description.multiple');
51631         }
51632     };
51633
51634
51635     operation.id = 'split';
51636     operation.keys = [t('operations.split.key')];
51637     operation.title = t('operations.split.title');
51638
51639
51640     return operation;
51641 }
51642
51643 function operationStraighten(selectedIDs, context) {
51644     var entityId = selectedIDs[0],
51645         action = actionStraighten(entityId, context.projection);
51646
51647
51648     function operation() {
51649         var annotation = t('operations.straighten.annotation');
51650         context.perform(action, annotation);
51651     }
51652
51653
51654     operation.available = function() {
51655         var entity = context.entity(entityId);
51656         return selectedIDs.length === 1 &&
51657             entity.type === 'way' &&
51658             !entity.isClosed() &&
51659             lodash.uniq(entity.nodes).length > 2;
51660     };
51661
51662
51663     operation.disabled = function() {
51664         var reason;
51665         if (context.hasHiddenConnections(entityId)) {
51666             reason = 'connected_to_hidden';
51667         }
51668         return action.disabled(context.graph()) || reason;
51669     };
51670
51671
51672     operation.tooltip = function() {
51673         var disable = operation.disabled();
51674         return disable ?
51675             t('operations.straighten.' + disable) :
51676             t('operations.straighten.description');
51677     };
51678
51679
51680     operation.id = 'straighten';
51681     operation.keys = [t('operations.straighten.key')];
51682     operation.title = t('operations.straighten.title');
51683
51684
51685     return operation;
51686 }
51687
51688
51689
51690 var Operations = Object.freeze({
51691         operationCircularize: operationCircularize,
51692         operationContinue: operationContinue,
51693         operationDelete: operationDelete,
51694         operationDisconnect: operationDisconnect,
51695         operationMerge: operationMerge,
51696         operationMove: operationMove,
51697         operationOrthogonalize: operationOrthogonalize,
51698         operationReverse: operationReverse,
51699         operationRotate: operationRotate,
51700         operationSplit: operationSplit,
51701         operationStraighten: operationStraighten
51702 });
51703
51704 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
51705 // For example, ⌘Z -> Ctrl+Z
51706 function uiCmd(code) {
51707     var detected = utilDetect();
51708
51709     if (detected.os === 'mac') {
51710         return code;
51711     }
51712
51713     if (detected.os === 'win') {
51714         if (code === '⌘⇧Z') return 'Ctrl+Y';
51715     }
51716
51717     var result = '',
51718         replacements = {
51719             '⌘': 'Ctrl',
51720             '⇧': 'Shift',
51721             '⌥': 'Alt',
51722             '⌫': 'Backspace',
51723             '⌦': 'Delete'
51724         };
51725
51726     for (var i = 0; i < code.length; i++) {
51727         if (code[i] in replacements) {
51728             result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
51729         } else {
51730             result += code[i];
51731         }
51732     }
51733
51734     return result;
51735 }
51736
51737 var relatedParent;
51738
51739
51740 function modeSelect(context, selectedIDs) {
51741     var mode = {
51742         id: 'select',
51743         button: 'browse'
51744     };
51745
51746     var keybinding = d3keybinding('select'),
51747         timeout$$1 = null,
51748         behaviors = [
51749             behaviorCopy(context),
51750             behaviorPaste(context),
51751             behaviorBreathe(context),
51752             behaviorHover(context),
51753             behaviorSelect(context),
51754             behaviorLasso(context),
51755             modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
51756         ],
51757         inspector,
51758         radialMenu,
51759         newFeature = false,
51760         suppressMenu = false,
51761         follow = false;
51762
51763
51764     var wrap = context.container()
51765         .select('.inspector-wrap');
51766
51767
51768     function singular() {
51769         if (selectedIDs.length === 1) {
51770             return context.hasEntity(selectedIDs[0]);
51771         }
51772     }
51773
51774
51775     function checkSelectedIDs() {
51776         var ids = [];
51777         if (Array.isArray(selectedIDs)) {
51778             ids = selectedIDs.filter(function(id) {
51779                 return context.hasEntity(id);
51780             });
51781         }
51782
51783         if (ids.length) {
51784             selectedIDs = ids;
51785         } else {
51786             context.enter(modeBrowse$$1(context));
51787         }
51788         return !!ids.length;
51789     }
51790
51791
51792     // find the common parent ways for nextVertex, previousVertex
51793     function commonParents() {
51794         var graph = context.graph(),
51795             commonParents = [];
51796
51797         for (var i = 0; i < selectedIDs.length; i++) {
51798             var entity = context.hasEntity(selectedIDs[i]);
51799             if (!entity || entity.geometry(graph) !== 'vertex') {
51800                 return [];  // selection includes some not vertexes
51801             }
51802
51803             var currParents = lodash.map(graph.parentWays(entity), 'id');
51804             if (!commonParents.length) {
51805                 commonParents = currParents;
51806                 continue;
51807             }
51808
51809             commonParents = lodash.intersection(commonParents, currParents);
51810             if (!commonParents.length) {
51811                 return [];
51812             }
51813         }
51814
51815         return commonParents;
51816     }
51817
51818
51819     function singularParent() {
51820         var parents = commonParents();
51821         if (!parents) {
51822             relatedParent = null;
51823             return null;
51824         }
51825
51826         // relatedParent is used when we visit a vertex with multiple
51827         // parents, and we want to remember which parent line we started on.
51828
51829         if (parents.length === 1) {
51830             relatedParent = parents[0];  // remember this parent for later
51831             return relatedParent;
51832         }
51833
51834         if (parents.indexOf(relatedParent) !== -1) {
51835             return relatedParent;   // prefer the previously seen parent
51836         }
51837
51838         return parents[0];
51839     }
51840
51841
51842     function closeMenu() {
51843         if (radialMenu) {
51844             context.surface().call(radialMenu.close);
51845         }
51846     }
51847
51848
51849     function positionMenu() {
51850         if (suppressMenu || !radialMenu) { return; }
51851
51852         var entity = singular();
51853         if (entity && context.geometry(entity.id) === 'relation') {
51854             suppressMenu = true;
51855         } else if (entity && entity.type === 'node') {
51856             radialMenu.center(context.projection(entity.loc));
51857         } else {
51858             var point = context.mouse(),
51859                 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
51860             if (geoPointInPolygon(point, viewport)) {
51861                 radialMenu.center(point);
51862             } else {
51863                 suppressMenu = true;
51864             }
51865         }
51866     }
51867
51868
51869     function showMenu() {
51870         closeMenu();
51871         if (!suppressMenu && radialMenu) {
51872             context.surface().call(radialMenu);
51873         }
51874     }
51875
51876
51877     function toggleMenu() {
51878         if (select('.radial-menu').empty()) {
51879             showMenu();
51880         } else {
51881             closeMenu();
51882         }
51883     }
51884
51885
51886     mode.selectedIDs = function() {
51887         return selectedIDs;
51888     };
51889
51890
51891     mode.reselect = function() {
51892         if (!checkSelectedIDs()) return;
51893
51894         var surfaceNode = context.surface().node();
51895         if (surfaceNode.focus) {   // FF doesn't support it
51896             surfaceNode.focus();
51897         }
51898
51899         positionMenu();
51900         showMenu();
51901     };
51902
51903
51904     mode.newFeature = function(_) {
51905         if (!arguments.length) return newFeature;
51906         newFeature = _;
51907         return mode;
51908     };
51909
51910
51911     mode.suppressMenu = function(_) {
51912         if (!arguments.length) return suppressMenu;
51913         suppressMenu = _;
51914         return mode;
51915     };
51916
51917
51918     mode.follow = function(_) {
51919         if (!arguments.length) return follow;
51920         follow = _;
51921         return mode;
51922     };
51923
51924
51925     mode.enter = function() {
51926
51927         function update() {
51928             closeMenu();
51929             checkSelectedIDs();
51930         }
51931
51932
51933         function dblclick() {
51934             var target = select(event.target),
51935                 datum = target.datum();
51936
51937             if (datum instanceof osmWay && !target.classed('fill')) {
51938                 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
51939                     node = osmNode();
51940
51941                 var prev = datum.nodes[choice.index - 1],
51942                     next = datum.nodes[choice.index];
51943
51944                 context.perform(
51945                     actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, node),
51946                     t('operations.add.annotation.vertex')
51947                 );
51948
51949                 event.preventDefault();
51950                 event.stopPropagation();
51951             }
51952         }
51953
51954
51955         function selectElements(drawn) {
51956             if (!checkSelectedIDs()) return;
51957
51958             var surface = context.surface(),
51959                 entity = singular();
51960
51961             if (entity && context.geometry(entity.id) === 'relation') {
51962                 suppressMenu = true;
51963                 return;
51964             }
51965
51966             surface.selectAll('.related')
51967                 .classed('related', false);
51968
51969             singularParent();
51970             if (relatedParent) {
51971                 surface.selectAll(utilEntitySelector([relatedParent]))
51972                     .classed('related', true);
51973             }
51974
51975             var selection$$1 = context.surface()
51976                 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
51977
51978             if (selection$$1.empty()) {
51979                 // Return to browse mode if selected DOM elements have
51980                 // disappeared because the user moved them out of view..
51981                 var source = event && event.type === 'zoom' && event.sourceEvent;
51982                 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
51983                     context.enter(modeBrowse$$1(context));
51984                 }
51985             } else {
51986                 selection$$1
51987                     .classed('selected', true);
51988             }
51989         }
51990
51991
51992         function esc() {
51993             if (!context.inIntro()) {
51994                 context.enter(modeBrowse$$1(context));
51995             }
51996         }
51997
51998
51999         function firstVertex() {
52000             event.preventDefault();
52001             var parent = singularParent();
52002             if (parent) {
52003                 var way = context.entity(parent);
52004                 context.enter(
52005                     modeSelect(context, [way.first()]).follow(true).suppressMenu(true)
52006                 );
52007             }
52008         }
52009
52010
52011         function lastVertex() {
52012             event.preventDefault();
52013             var parent = singularParent();
52014             if (parent) {
52015                 var way = context.entity(parent);
52016                 context.enter(
52017                     modeSelect(context, [way.last()]).follow(true).suppressMenu(true)
52018                 );
52019             }
52020         }
52021
52022
52023         function previousVertex() {
52024             event.preventDefault();
52025             var parent = singularParent();
52026             if (!parent) return;
52027
52028             var way = context.entity(parent),
52029                 length = way.nodes.length,
52030                 curr = way.nodes.indexOf(selectedIDs[0]),
52031                 index = -1;
52032
52033             if (curr > 0) {
52034                 index = curr - 1;
52035             } else if (way.isClosed()) {
52036                 index = length - 2;
52037             }
52038
52039             if (index !== -1) {
52040                 context.enter(
52041                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52042                 );
52043             }
52044         }
52045
52046
52047         function nextVertex() {
52048             event.preventDefault();
52049             var parent = singularParent();
52050             if (!parent) return;
52051
52052             var way = context.entity(parent),
52053                 length = way.nodes.length,
52054                 curr = way.nodes.indexOf(selectedIDs[0]),
52055                 index = -1;
52056
52057             if (curr < length - 1) {
52058                 index = curr + 1;
52059             } else if (way.isClosed()) {
52060                 index = 0;
52061             }
52062
52063             if (index !== -1) {
52064                 context.enter(
52065                     modeSelect(context, [way.nodes[index]]).follow(true).suppressMenu(true)
52066                 );
52067             }
52068         }
52069
52070
52071         function nextParent() {
52072             event.preventDefault();
52073             var parents = lodash.uniq(commonParents());
52074             if (!parents || parents.length < 2) return;
52075
52076             var index = parents.indexOf(relatedParent);
52077             if (index < 0 || index > parents.length - 2) {
52078                 relatedParent = parents[0];
52079             } else {
52080                 relatedParent = parents[index + 1];
52081             }
52082
52083             var surface = context.surface();
52084             surface.selectAll('.related')
52085                 .classed('related', false);
52086
52087             if (relatedParent) {
52088                 surface.selectAll(utilEntitySelector([relatedParent]))
52089                     .classed('related', true);
52090             }
52091         }
52092
52093
52094         if (!checkSelectedIDs()) return;
52095
52096         behaviors.forEach(function(behavior) {
52097             context.install(behavior);
52098         });
52099
52100         var operations = lodash.without(values(Operations), operationDelete)
52101                 .map(function(o) { return o(selectedIDs, context); })
52102                 .filter(function(o) { return o.available(); });
52103
52104         operations.unshift(operationDelete(selectedIDs, context));
52105
52106         keybinding
52107             .on(['[','pgup'], previousVertex)
52108             .on([']', 'pgdown'], nextVertex)
52109             .on([uiCmd('⌘['), 'home'], firstVertex)
52110             .on([uiCmd('⌘]'), 'end'], lastVertex)
52111             .on(['\\', 'pause'], nextParent)
52112             .on('⎋', esc, true)
52113             .on('space', toggleMenu);
52114
52115         operations.forEach(function(operation) {
52116             operation.keys.forEach(function(key) {
52117                 keybinding.on(key, function() {
52118                     if (!(context.inIntro() || operation.disabled())) {
52119                         operation();
52120                     }
52121                 });
52122             });
52123         });
52124
52125         select(document)
52126             .call(keybinding);
52127
52128         radialMenu = uiRadialMenu(context, operations);
52129
52130         context.ui().sidebar
52131             .select(singular() ? singular().id : null, newFeature);
52132
52133         context.history()
52134             .on('undone.select', update)
52135             .on('redone.select', update);
52136
52137         context.map()
52138             .on('move.select', closeMenu)
52139             .on('drawn.select', selectElements);
52140
52141         selectElements();
52142
52143         var show = event && !suppressMenu;
52144
52145         if (show) {
52146             positionMenu();
52147         }
52148
52149         if (follow) {
52150             var extent$$1 = geoExtent$$1(),
52151                 graph = context.graph();
52152             selectedIDs.forEach(function(id) {
52153                 var entity = context.entity(id);
52154                 extent$$1._extend(entity.extent(graph));
52155             });
52156
52157             var loc = extent$$1.center();
52158             context.map().centerEase(loc);
52159         }
52160
52161         timeout$$1 = window.setTimeout(function() {
52162             if (show) {
52163                 showMenu();
52164             }
52165
52166             context.surface()
52167                 .on('dblclick.select', dblclick);
52168         }, 200);
52169
52170         if (selectedIDs.length > 1) {
52171             var entities = uiSelectionList(context, selectedIDs);
52172             context.ui().sidebar.show(entities);
52173         }
52174     };
52175
52176
52177     mode.exit = function() {
52178         if (timeout$$1) window.clearTimeout(timeout$$1);
52179
52180         if (inspector) wrap.call(inspector.close);
52181
52182         behaviors.forEach(function(behavior) {
52183             context.uninstall(behavior);
52184         });
52185
52186         keybinding.off();
52187         closeMenu();
52188         radialMenu = undefined;
52189
52190         context.history()
52191             .on('undone.select', null)
52192             .on('redone.select', null);
52193
52194         var surface = context.surface();
52195
52196         surface
52197             .on('dblclick.select', null);
52198
52199         surface
52200             .selectAll('.selected')
52201             .classed('selected', false);
52202
52203         surface
52204             .selectAll('.related')
52205             .classed('related', false);
52206
52207         context.map().on('drawn.select', null);
52208         context.ui().sidebar.hide();
52209     };
52210
52211
52212     return mode;
52213 }
52214
52215 function uiAccount(context) {
52216     var connection = context.connection();
52217
52218
52219     function update(selection$$1) {
52220         if (!connection.authenticated()) {
52221             selection$$1.selectAll('#userLink, #logoutLink')
52222                 .classed('hide', true);
52223             return;
52224         }
52225
52226         connection.userDetails(function(err, details) {
52227             var userLink = selection$$1.select('#userLink'),
52228                 logoutLink = selection$$1.select('#logoutLink');
52229
52230             userLink.html('');
52231             logoutLink.html('');
52232
52233             if (err) return;
52234
52235             selection$$1.selectAll('#userLink, #logoutLink')
52236                 .classed('hide', false);
52237
52238             // Link
52239             userLink.append('a')
52240                 .attr('href', connection.userURL(details.display_name))
52241                 .attr('target', '_blank');
52242
52243             // Add thumbnail or dont
52244             if (details.image_url) {
52245                 userLink.append('img')
52246                     .attr('class', 'icon pre-text user-icon')
52247                     .attr('src', details.image_url);
52248             } else {
52249                 userLink
52250                     .call(svgIcon('#icon-avatar', 'pre-text light'));
52251             }
52252
52253             // Add user name
52254             userLink.append('span')
52255                 .attr('class', 'label')
52256                 .text(details.display_name);
52257
52258             logoutLink.append('a')
52259                 .attr('class', 'logout')
52260                 .attr('href', '#')
52261                 .text(t('logout'))
52262                 .on('click.logout', function() {
52263                     event.preventDefault();
52264                     connection.logout();
52265                 });
52266         });
52267     }
52268
52269
52270     return function(selection$$1) {
52271         selection$$1.append('li')
52272             .attr('id', 'logoutLink')
52273             .classed('hide', true);
52274
52275         selection$$1.append('li')
52276             .attr('id', 'userLink')
52277             .classed('hide', true);
52278
52279         connection
52280             .on('change.account', function() { update(selection$$1); });
52281
52282         update(selection$$1);
52283     };
52284 }
52285
52286 function uiAttribution(context) {
52287     var selection$$1;
52288
52289
52290     function attribution(data, klass) {
52291         var div = selection$$1.selectAll('.' + klass)
52292             .data([0]);
52293
52294         div = div.enter()
52295             .append('div')
52296             .attr('class', klass)
52297             .merge(div);
52298
52299
52300         var background = div.selectAll('.attribution')
52301             .data(data, function(d) { return d.name(); });
52302
52303         background.exit()
52304             .remove();
52305
52306         background = background.enter()
52307             .append('span')
52308             .attr('class', 'attribution')
52309             .each(function(d) {
52310                 if (d.terms_html) {
52311                     select(this)
52312                         .html(d.terms_html);
52313                     return;
52314                 }
52315
52316                 var source = d.terms_text || d.id || d.name();
52317
52318                 if (d.logo) {
52319                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
52320                 }
52321
52322                 if (d.terms_url) {
52323                     select(this)
52324                         .append('a')
52325                         .attr('href', d.terms_url)
52326                         .attr('target', '_blank')
52327                         .html(source);
52328                 } else {
52329                     select(this)
52330                         .text(source);
52331                 }
52332             })
52333             .merge(background);
52334
52335
52336         var copyright = background.selectAll('.copyright-notice')
52337             .data(function(d) {
52338                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
52339                 return notice ? [notice] : [];
52340             });
52341
52342         copyright.exit()
52343             .remove();
52344
52345         copyright = copyright.enter()
52346             .append('span')
52347             .attr('class', 'copyright-notice')
52348             .merge(copyright);
52349
52350         copyright
52351             .text(String);
52352     }
52353
52354
52355     function update() {
52356         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
52357         attribution(context.background().overlayLayerSources().filter(function (s) {
52358             return s.validZoom(context.map().zoom());
52359         }), 'overlay-layer-attribution');
52360     }
52361
52362
52363     return function(select$$1) {
52364         selection$$1 = select$$1;
52365
52366         context.background()
52367             .on('change.attribution', update);
52368
52369         context.map()
52370             .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
52371
52372         update();
52373     };
52374 }
52375
52376 function rendererBackgroundSource(data) {
52377     var source = lodash.clone(data),
52378         offset = [0, 0],
52379         name = source.name,
52380         best = !!source.best;
52381
52382     source.scaleExtent = data.scaleExtent || [0, 20];
52383     source.overzoom = data.overzoom !== false;
52384
52385
52386     source.offset = function(_) {
52387         if (!arguments.length) return offset;
52388         offset = _;
52389         return source;
52390     };
52391
52392
52393     source.nudge = function(_, zoomlevel) {
52394         offset[0] += _[0] / Math.pow(2, zoomlevel);
52395         offset[1] += _[1] / Math.pow(2, zoomlevel);
52396         return source;
52397     };
52398
52399
52400     source.name = function() {
52401         return name;
52402     };
52403
52404
52405     source.best = function() {
52406         return best;
52407     };
52408
52409
52410     source.area = function() {
52411         if (!data.polygon) return Number.MAX_VALUE;  // worldwide
52412         var area$$1 = area$1({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
52413         return isNaN(area$$1) ? 0 : area$$1;
52414     };
52415
52416
52417     source.imageryUsed = function() {
52418         return name || source.id;
52419     };
52420
52421
52422     source.url = function(coord) {
52423         return data.template
52424             .replace('{x}', coord[0])
52425             .replace('{y}', coord[1])
52426             // TMS-flipped y coordinate
52427             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
52428             .replace(/\{z(oom)?\}/, coord[2])
52429             .replace(/\{switch:([^}]+)\}/, function(s, r) {
52430                 var subdomains = r.split(',');
52431                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
52432             })
52433             .replace('{u}', function() {
52434                 var u = '';
52435                 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
52436                     var b = 0;
52437                     var mask = 1 << (zoom$$1 - 1);
52438                     if ((coord[0] & mask) !== 0) b++;
52439                     if ((coord[1] & mask) !== 0) b += 2;
52440                     u += b.toString();
52441                 }
52442                 return u;
52443             });
52444     };
52445
52446
52447     source.intersects = function(extent$$1) {
52448         extent$$1 = extent$$1.polygon();
52449         return !data.polygon || data.polygon.some(function(polygon) {
52450             return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
52451         });
52452     };
52453
52454
52455     source.validZoom = function(z) {
52456         return source.scaleExtent[0] <= z &&
52457             (source.overzoom || source.scaleExtent[1] > z);
52458     };
52459
52460
52461     source.isLocatorOverlay = function() {
52462         return source.id === 'mapbox_locator_overlay';
52463     };
52464
52465
52466     source.copyrightNotices = function() {};
52467
52468
52469     return source;
52470 }
52471
52472
52473 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
52474     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
52475     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
52476
52477     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
52478
52479     var bing = rendererBackgroundSource(data),
52480         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
52481         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
52482             key + '&jsonp={callback}',
52483         providers = [];
52484
52485     jsonpRequest(url, function(json$$1) {
52486         providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
52487             return {
52488                 attribution: provider.attribution,
52489                 areas: provider.coverageAreas.map(function(area$$1) {
52490                     return {
52491                         zoom: [area$$1.zoomMin, area$$1.zoomMax],
52492                         extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
52493                     };
52494                 })
52495             };
52496         });
52497         dispatch$$1.call('change');
52498     });
52499
52500     bing.copyrightNotices = function(zoom$$1, extent$$1) {
52501         zoom$$1 = Math.min(zoom$$1, 21);
52502         return providers.filter(function(provider) {
52503             return lodash.some(provider.areas, function(area$$1) {
52504                 return extent$$1.intersects(area$$1.extent) &&
52505                     area$$1.zoom[0] <= zoom$$1 &&
52506                     area$$1.zoom[1] >= zoom$$1;
52507             });
52508         }).map(function(provider) {
52509             return provider.attribution;
52510         }).join(', ');
52511     };
52512
52513     bing.logo = 'bing_maps.png';
52514     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
52515
52516     return bing;
52517 };
52518
52519
52520 rendererBackgroundSource.None = function() {
52521     var source = rendererBackgroundSource({ id: 'none', template: '' });
52522
52523     source.name = function() {
52524         return t('background.none');
52525     };
52526
52527     source.imageryUsed = function() {
52528         return 'None';
52529     };
52530
52531     source.area = function() {
52532         return -1;  // sources in background pane are sorted by area
52533     };
52534
52535     return source;
52536 };
52537
52538
52539 rendererBackgroundSource.Custom = function(template) {
52540     var source = rendererBackgroundSource({ id: 'custom', template: template });
52541
52542     source.name = function() {
52543         return t('background.custom');
52544     };
52545
52546     source.imageryUsed = function() {
52547         return 'Custom (' + template + ')';
52548     };
52549
52550     source.area = function() {
52551         return -2;  // sources in background pane are sorted by area
52552     };
52553
52554     return source;
52555 };
52556
52557 function rendererTileLayer(context) {
52558     var tileSize = 256,
52559         tile = d3geoTile(),
52560         projection,
52561         cache = {},
52562         tileOrigin,
52563         z,
52564         transformProp = utilPrefixCSSProperty('Transform'),
52565         source = rendererBackgroundSource.None();
52566
52567
52568     // blacklist overlay tiles around Null Island..
52569     function nearNullIsland(x, y, z) {
52570         if (z >= 7) {
52571             var center = Math.pow(2, z - 1),
52572                 width = Math.pow(2, z - 6),
52573                 min$$1 = center - (width / 2),
52574                 max$$1 = center + (width / 2) - 1;
52575             return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
52576         }
52577         return false;
52578     }
52579
52580
52581     function tileSizeAtZoom(d, z) {
52582         var epsilon = 0.002;
52583         return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
52584     }
52585
52586
52587     function atZoom(t, distance) {
52588         var power = Math.pow(2, distance);
52589         return [
52590             Math.floor(t[0] * power),
52591             Math.floor(t[1] * power),
52592             t[2] + distance];
52593     }
52594
52595
52596     function lookUp(d) {
52597         for (var up = -1; up > -d[2]; up--) {
52598             var tile = atZoom(d, up);
52599             if (cache[source.url(tile)] !== false) {
52600                 return tile;
52601             }
52602         }
52603     }
52604
52605
52606     function uniqueBy(a, n) {
52607         var o = [], seen = {};
52608         for (var i = 0; i < a.length; i++) {
52609             if (seen[a[i][n]] === undefined) {
52610                 o.push(a[i]);
52611                 seen[a[i][n]] = true;
52612             }
52613         }
52614         return o;
52615     }
52616
52617
52618     function addSource(d) {
52619         d.push(source.url(d));
52620         return d;
52621     }
52622
52623
52624     // Update tiles based on current state of `projection`.
52625     function background(selection$$1) {
52626         tile.scale(projection.scale() * 2 * Math.PI)
52627             .translate(projection.translate());
52628
52629         tileOrigin = [
52630             projection.scale() * Math.PI - projection.translate()[0],
52631             projection.scale() * Math.PI - projection.translate()[1]];
52632
52633         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
52634
52635         render(selection$$1);
52636     }
52637
52638
52639     // Derive the tiles onscreen, remove those offscreen and position them.
52640     // Important that this part not depend on `projection` because it's
52641     // rentered when tiles load/error (see #644).
52642     function render(selection$$1) {
52643         var requests = [];
52644         var showDebug = context.getDebug('tile') && !source.overlay;
52645
52646         if (source.validZoom(z)) {
52647             tile().forEach(function(d) {
52648                 addSource(d);
52649                 if (d[3] === '') return;
52650                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
52651                 requests.push(d);
52652                 if (cache[d[3]] === false && lookUp(d)) {
52653                     requests.push(addSource(lookUp(d)));
52654                 }
52655             });
52656
52657             requests = uniqueBy(requests, 3).filter(function(r) {
52658                 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
52659                     return false;
52660                 }
52661                 // don't re-request tiles which have failed in the past
52662                 return cache[r[3]] !== false;
52663             });
52664         }
52665
52666         var pixelOffset = [
52667             source.offset()[0] * Math.pow(2, z),
52668             source.offset()[1] * Math.pow(2, z)
52669         ];
52670
52671         function load(d) {
52672             cache[d[3]] = true;
52673             select(this)
52674                 .on('error', null)
52675                 .on('load', null)
52676                 .classed('tile-loaded', true);
52677             render(selection$$1);
52678         }
52679
52680         function error(d) {
52681             cache[d[3]] = false;
52682             select(this)
52683                 .on('error', null)
52684                 .on('load', null)
52685                 .remove();
52686             render(selection$$1);
52687         }
52688
52689         function imageTransform(d) {
52690             var _ts = tileSize * Math.pow(2, z - d[2]);
52691             var scale = tileSizeAtZoom(d, z);
52692             return 'translate(' +
52693                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
52694                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
52695                 'scale(' + scale + ',' + scale + ')';
52696         }
52697
52698         function debugTransform(d) {
52699             var _ts = tileSize * Math.pow(2, z - d[2]);
52700             var scale = tileSizeAtZoom(d, z);
52701             return 'translate(' +
52702                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
52703                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
52704         }
52705
52706
52707         var image = selection$$1.selectAll('img')
52708             .data(requests, function(d) { return d[3]; });
52709
52710         image.exit()
52711             .style(transformProp, imageTransform)
52712             .classed('tile-removing', true)
52713             .each(function() {
52714                 var tile = select(this);
52715                 window.setTimeout(function() {
52716                     if (tile.classed('tile-removing')) {
52717                         tile.remove();
52718                     }
52719                 }, 300);
52720             });
52721
52722         image.enter()
52723           .append('img')
52724             .attr('class', 'tile')
52725             .attr('src', function(d) { return d[3]; })
52726             .on('error', error)
52727             .on('load', load)
52728           .merge(image)
52729             .style(transformProp, imageTransform)
52730             .classed('tile-debug', showDebug)
52731             .classed('tile-removing', false);
52732
52733
52734         var debug = selection$$1.selectAll('.tile-label-debug')
52735             .data(showDebug ? requests : [], function(d) { return d[3]; });
52736
52737         debug.exit()
52738             .remove();
52739
52740         debug.enter()
52741           .append('div')
52742             .attr('class', 'tile-label-debug')
52743           .merge(debug)
52744             .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
52745             .style(transformProp, debugTransform);
52746     }
52747
52748
52749     background.projection = function(_) {
52750         if (!arguments.length) return projection;
52751         projection = _;
52752         return background;
52753     };
52754
52755
52756     background.dimensions = function(_) {
52757         if (!arguments.length) return tile.size();
52758         tile.size(_);
52759         return background;
52760     };
52761
52762
52763     background.source = function(_) {
52764         if (!arguments.length) return source;
52765         source = _;
52766         cache = {};
52767         tile.scaleExtent(source.scaleExtent);
52768         return background;
52769     };
52770
52771
52772     return background;
52773 }
52774
52775 function rendererBackground(context) {
52776     var dispatch$$1 = dispatch('change'),
52777         baseLayer = rendererTileLayer(context).projection(context.projection),
52778         overlayLayers = [],
52779         backgroundSources;
52780
52781
52782     function findSource(id) {
52783         return lodash.find(backgroundSources, function(d) {
52784             return d.id && d.id === id;
52785         });
52786     }
52787
52788
52789     function background(selection$$1) {
52790         var base = selection$$1.selectAll('.layer-background')
52791             .data([0]);
52792
52793         base.enter()
52794             .insert('div', '.layer-data')
52795             .attr('class', 'layer layer-background')
52796             .merge(base)
52797             .call(baseLayer);
52798
52799         var overlays = selection$$1.selectAll('.layer-overlay')
52800             .data(overlayLayers, function(d) { return d.source().name(); });
52801
52802         overlays.exit()
52803             .remove();
52804
52805         overlays.enter()
52806             .insert('div', '.layer-data')
52807             .attr('class', 'layer layer-overlay')
52808             .merge(overlays)
52809             .each(function(layer) { select(this).call(layer); });
52810     }
52811
52812
52813     background.updateImagery = function() {
52814         var b = background.baseLayerSource(),
52815             o = overlayLayers
52816                 .filter(function (d) { return !d.source().isLocatorOverlay(); })
52817                 .map(function (d) { return d.source().id; })
52818                 .join(','),
52819             meters = geoOffsetToMeters(b.offset()),
52820             epsilon = 0.01,
52821             x = +meters[0].toFixed(2),
52822             y = +meters[1].toFixed(2),
52823             q = utilStringQs(window.location.hash.substring(1));
52824
52825         var id = b.id;
52826         if (id === 'custom') {
52827             id = 'custom:' + b.template;
52828         }
52829
52830         if (id) {
52831             q.background = id;
52832         } else {
52833             delete q.background;
52834         }
52835
52836         if (o) {
52837             q.overlays = o;
52838         } else {
52839             delete q.overlays;
52840         }
52841
52842         if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
52843             q.offset = x + ',' + y;
52844         } else {
52845             delete q.offset;
52846         }
52847
52848         window.location.replace('#' + utilQsString(q, true));
52849
52850         var imageryUsed = [b.imageryUsed()];
52851
52852         overlayLayers
52853             .filter(function (d) { return !d.source().isLocatorOverlay(); })
52854             .forEach(function (d) { imageryUsed.push(d.source().imageryUsed()); });
52855
52856         var gpx = context.layers().layer('gpx');
52857         if (gpx && gpx.enabled() && gpx.hasGpx()) {
52858             imageryUsed.push('Local GPX');
52859         }
52860
52861         var mapillary_images = context.layers().layer('mapillary-images');
52862         if (mapillary_images && mapillary_images.enabled()) {
52863             imageryUsed.push('Mapillary Images');
52864         }
52865
52866         var mapillary_signs = context.layers().layer('mapillary-signs');
52867         if (mapillary_signs && mapillary_signs.enabled()) {
52868             imageryUsed.push('Mapillary Signs');
52869         }
52870
52871         context.history().imageryUsed(imageryUsed);
52872     };
52873
52874
52875     background.sources = function(extent$$1) {
52876         return backgroundSources.filter(function(source) {
52877             return source.intersects(extent$$1);
52878         });
52879     };
52880
52881
52882     background.dimensions = function(_) {
52883         if (!_) return;
52884         baseLayer.dimensions(_);
52885
52886         overlayLayers.forEach(function(layer) {
52887             layer.dimensions(_);
52888         });
52889     };
52890
52891
52892     background.baseLayerSource = function(d) {
52893         if (!arguments.length) return baseLayer.source();
52894
52895         // test source against OSM imagery blacklists..
52896         var blacklists = context.connection().imageryBlacklists();
52897
52898         var fail = false,
52899             tested = 0,
52900             regex, i;
52901
52902         for (i = 0; i < blacklists; i++) {
52903             try {
52904                 regex = new RegExp(blacklists[i]);
52905                 fail = regex.test(d.template);
52906                 tested++;
52907                 if (fail) break;
52908             } catch (e) {
52909                 /* noop */
52910             }
52911         }
52912
52913         // ensure at least one test was run.
52914         if (!tested) {
52915             regex = new RegExp('.*\.google(apis)?\..*/(vt|kh)[\?/].*([xyz]=.*){3}.*');
52916             fail = regex.test(d.template);
52917         }
52918
52919         baseLayer.source(!fail ? d : rendererBackgroundSource.None());
52920         dispatch$$1.call('change');
52921         background.updateImagery();
52922         return background;
52923     };
52924
52925
52926     background.bing = function() {
52927         background.baseLayerSource(findSource('Bing'));
52928     };
52929
52930
52931     background.showsLayer = function(d) {
52932         return d.id === baseLayer.source().id ||
52933             overlayLayers.some(function(layer) { return d.id === layer.source().id; });
52934     };
52935
52936
52937     background.overlayLayerSources = function() {
52938         return overlayLayers.map(function (l) { return l.source(); });
52939     };
52940
52941
52942     background.toggleOverlayLayer = function(d) {
52943         var layer;
52944
52945         for (var i = 0; i < overlayLayers.length; i++) {
52946             layer = overlayLayers[i];
52947             if (layer.source() === d) {
52948                 overlayLayers.splice(i, 1);
52949                 dispatch$$1.call('change');
52950                 background.updateImagery();
52951                 return;
52952             }
52953         }
52954
52955         layer = rendererTileLayer(context)
52956             .source(d)
52957             .projection(context.projection)
52958             .dimensions(baseLayer.dimensions());
52959
52960         overlayLayers.push(layer);
52961         dispatch$$1.call('change');
52962         background.updateImagery();
52963     };
52964
52965
52966     background.nudge = function(d, zoom$$1) {
52967         baseLayer.source().nudge(d, zoom$$1);
52968         dispatch$$1.call('change');
52969         background.updateImagery();
52970         return background;
52971     };
52972
52973
52974     background.offset = function(d) {
52975         if (!arguments.length) return baseLayer.source().offset();
52976         baseLayer.source().offset(d);
52977         dispatch$$1.call('change');
52978         background.updateImagery();
52979         return background;
52980     };
52981
52982
52983     background.init = function() {
52984         function parseMap(qmap) {
52985             if (!qmap) return false;
52986             var args = qmap.split('/').map(Number);
52987             if (args.length < 3 || args.some(isNaN)) return false;
52988             return geoExtent$$1([args[2], args[1]]);
52989         }
52990
52991         var dataImagery = data.imagery || [],
52992             q = utilStringQs(window.location.hash.substring(1)),
52993             chosen = q.background || q.layer,
52994             extent$$1 = parseMap(q.map),
52995             best;
52996
52997         backgroundSources = dataImagery.map(function(source) {
52998             if (source.type === 'bing') {
52999                 return rendererBackgroundSource.Bing(source, dispatch$$1);
53000             } else {
53001                 return rendererBackgroundSource(source);
53002             }
53003         });
53004
53005         backgroundSources.unshift(rendererBackgroundSource.None());
53006
53007         if (!chosen && extent$$1) {
53008             best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
53009         }
53010
53011         if (chosen && chosen.indexOf('custom:') === 0) {
53012             background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
53013         } else {
53014             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
53015         }
53016
53017         var locator = lodash.find(backgroundSources, function(d) {
53018             return d.overlay && d.default;
53019         });
53020
53021         if (locator) {
53022             background.toggleOverlayLayer(locator);
53023         }
53024
53025         var overlays = (q.overlays || '').split(',');
53026         overlays.forEach(function(overlay) {
53027             overlay = findSource(overlay);
53028             if (overlay) {
53029                 background.toggleOverlayLayer(overlay);
53030             }
53031         });
53032
53033         if (q.gpx) {
53034             var gpx = context.layers().layer('gpx');
53035             if (gpx) {
53036                 gpx.url(q.gpx);
53037             }
53038         }
53039
53040         if (q.offset) {
53041             var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
53042                 return !isNaN(n) && n;
53043             });
53044
53045             if (offset.length === 2) {
53046                 background.offset(geoMetersToOffset(offset));
53047             }
53048         }
53049     };
53050
53051
53052     return utilRebind(background, dispatch$$1, 'on');
53053 }
53054
53055 function rendererFeatures(context) {
53056     var traffic_roads = {
53057         'motorway': true,
53058         'motorway_link': true,
53059         'trunk': true,
53060         'trunk_link': true,
53061         'primary': true,
53062         'primary_link': true,
53063         'secondary': true,
53064         'secondary_link': true,
53065         'tertiary': true,
53066         'tertiary_link': true,
53067         'residential': true,
53068         'unclassified': true,
53069         'living_street': true
53070     };
53071
53072     var service_roads = {
53073         'service': true,
53074         'road': true,
53075         'track': true
53076     };
53077
53078     var paths = {
53079         'path': true,
53080         'footway': true,
53081         'cycleway': true,
53082         'bridleway': true,
53083         'steps': true,
53084         'pedestrian': true,
53085         'corridor': true
53086     };
53087
53088     var past_futures = {
53089         'proposed': true,
53090         'construction': true,
53091         'abandoned': true,
53092         'dismantled': true,
53093         'disused': true,
53094         'razed': true,
53095         'demolished': true,
53096         'obliterated': true
53097     };
53098
53099     var dispatch$$1 = dispatch('change', 'redraw'),
53100         _cullFactor = 1,
53101         _cache = {},
53102         _features = {},
53103         _stats = {},
53104         _keys = [],
53105         _hidden = [];
53106
53107
53108     function update() {
53109         _hidden = features.hidden();
53110         dispatch$$1.call('change');
53111         dispatch$$1.call('redraw');
53112     }
53113
53114
53115     function defineFeature(k, filter, max$$1) {
53116         _keys.push(k);
53117         _features[k] = {
53118             filter: filter,
53119             enabled: true,   // whether the user wants it enabled..
53120             count: 0,
53121             currentMax: (max$$1 || Infinity),
53122             defaultMax: (max$$1 || Infinity),
53123             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
53124             disable: function() { this.enabled = false; this.currentMax = 0; },
53125             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
53126             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
53127         };
53128     }
53129
53130
53131     defineFeature('points', function isPoint(entity, resolver, geometry) {
53132         return geometry === 'point';
53133     }, 200);
53134
53135     defineFeature('traffic_roads', function isTrafficRoad(entity) {
53136         return traffic_roads[entity.tags.highway];
53137     });
53138
53139     defineFeature('service_roads', function isServiceRoad(entity) {
53140         return service_roads[entity.tags.highway];
53141     });
53142
53143     defineFeature('paths', function isPath(entity) {
53144         return paths[entity.tags.highway];
53145     });
53146
53147     defineFeature('buildings', function isBuilding(entity) {
53148         return (
53149             !!entity.tags['building:part'] ||
53150             (!!entity.tags.building && entity.tags.building !== 'no') ||
53151             entity.tags.amenity === 'shelter' ||
53152             entity.tags.parking === 'multi-storey' ||
53153             entity.tags.parking === 'sheds' ||
53154             entity.tags.parking === 'carports' ||
53155             entity.tags.parking === 'garage_boxes'
53156         );
53157     }, 250);
53158
53159     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
53160         return geometry === 'area' &&
53161             !_features.buildings.filter(entity) &&
53162             !_features.water.filter(entity);
53163     });
53164
53165     defineFeature('boundaries', function isBoundary(entity) {
53166         return !!entity.tags.boundary;
53167     });
53168
53169     defineFeature('water', function isWater(entity) {
53170         return (
53171             !!entity.tags.waterway ||
53172             entity.tags.natural === 'water' ||
53173             entity.tags.natural === 'coastline' ||
53174             entity.tags.natural === 'bay' ||
53175             entity.tags.landuse === 'pond' ||
53176             entity.tags.landuse === 'basin' ||
53177             entity.tags.landuse === 'reservoir' ||
53178             entity.tags.landuse === 'salt_pond'
53179         );
53180     });
53181
53182     defineFeature('rail', function isRail(entity) {
53183         return (
53184             !!entity.tags.railway ||
53185             entity.tags.landuse === 'railway'
53186         ) && !(
53187             traffic_roads[entity.tags.highway] ||
53188             service_roads[entity.tags.highway] ||
53189             paths[entity.tags.highway]
53190         );
53191     });
53192
53193     defineFeature('power', function isPower(entity) {
53194         return !!entity.tags.power;
53195     });
53196
53197     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
53198     defineFeature('past_future', function isPastFuture(entity) {
53199         if (
53200             traffic_roads[entity.tags.highway] ||
53201             service_roads[entity.tags.highway] ||
53202             paths[entity.tags.highway]
53203         ) { return false; }
53204
53205         var strings = Object.keys(entity.tags);
53206
53207         for (var i = 0; i < strings.length; i++) {
53208             var s = strings[i];
53209             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
53210         }
53211         return false;
53212     });
53213
53214     // Lines or areas that don't match another feature filter.
53215     // IMPORTANT: The 'others' feature must be the last one defined,
53216     //   so that code in getMatches can skip this test if `hasMatch = true`
53217     defineFeature('others', function isOther(entity, resolver, geometry) {
53218         return (geometry === 'line' || geometry === 'area');
53219     });
53220
53221
53222     function features() {}
53223
53224
53225     features.features = function() {
53226         return _features;
53227     };
53228
53229
53230     features.keys = function() {
53231         return _keys;
53232     };
53233
53234
53235     features.enabled = function(k) {
53236         if (!arguments.length) {
53237             return _keys.filter(function(k) { return _features[k].enabled; });
53238         }
53239         return _features[k] && _features[k].enabled;
53240     };
53241
53242
53243     features.disabled = function(k) {
53244         if (!arguments.length) {
53245             return _keys.filter(function(k) { return !_features[k].enabled; });
53246         }
53247         return _features[k] && !_features[k].enabled;
53248     };
53249
53250
53251     features.hidden = function(k) {
53252         if (!arguments.length) {
53253             return _keys.filter(function(k) { return _features[k].hidden(); });
53254         }
53255         return _features[k] && _features[k].hidden();
53256     };
53257
53258
53259     features.autoHidden = function(k) {
53260         if (!arguments.length) {
53261             return _keys.filter(function(k) { return _features[k].autoHidden(); });
53262         }
53263         return _features[k] && _features[k].autoHidden();
53264     };
53265
53266
53267     features.enable = function(k) {
53268         if (_features[k] && !_features[k].enabled) {
53269             _features[k].enable();
53270             update();
53271         }
53272     };
53273
53274
53275     features.disable = function(k) {
53276         if (_features[k] && _features[k].enabled) {
53277             _features[k].disable();
53278             update();
53279         }
53280     };
53281
53282
53283     features.toggle = function(k) {
53284         if (_features[k]) {
53285             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
53286             update();
53287         }
53288     };
53289
53290
53291     features.resetStats = function() {
53292         for (var i = 0; i < _keys.length; i++) {
53293             _features[_keys[i]].count = 0;
53294         }
53295         dispatch$$1.call('change');
53296     };
53297
53298
53299     features.gatherStats = function(d, resolver, dimensions) {
53300         var needsRedraw = false,
53301             type = lodash.groupBy(d, function(ent) { return ent.type; }),
53302             entities = [].concat(type.relation || [], type.way || [], type.node || []),
53303             currHidden, geometry, matches, i, j;
53304
53305         for (i = 0; i < _keys.length; i++) {
53306             _features[_keys[i]].count = 0;
53307         }
53308
53309         // adjust the threshold for point/building culling based on viewport size..
53310         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
53311         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
53312
53313         for (i = 0; i < entities.length; i++) {
53314             geometry = entities[i].geometry(resolver);
53315             if (!(geometry === 'vertex' || geometry === 'relation')) {
53316                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
53317                 for (j = 0; j < matches.length; j++) {
53318                     _features[matches[j]].count++;
53319                 }
53320             }
53321         }
53322
53323         currHidden = features.hidden();
53324         if (currHidden !== _hidden) {
53325             _hidden = currHidden;
53326             needsRedraw = true;
53327             dispatch$$1.call('change');
53328         }
53329
53330         return needsRedraw;
53331     };
53332
53333
53334     features.stats = function() {
53335         for (var i = 0; i < _keys.length; i++) {
53336             _stats[_keys[i]] = _features[_keys[i]].count;
53337         }
53338
53339         return _stats;
53340     };
53341
53342
53343     features.clear = function(d) {
53344         for (var i = 0; i < d.length; i++) {
53345             features.clearEntity(d[i]);
53346         }
53347     };
53348
53349
53350     features.clearEntity = function(entity) {
53351         delete _cache[osmEntity$$1.key(entity)];
53352     };
53353
53354
53355     features.reset = function() {
53356         _cache = {};
53357     };
53358
53359
53360     features.getMatches = function(entity, resolver, geometry) {
53361         if (geometry === 'vertex' || geometry === 'relation') return {};
53362
53363         var ent = osmEntity$$1.key(entity);
53364         if (!_cache[ent]) {
53365             _cache[ent] = {};
53366         }
53367
53368         if (!_cache[ent].matches) {
53369             var matches = {},
53370                 hasMatch = false;
53371
53372             for (var i = 0; i < _keys.length; i++) {
53373                 if (_keys[i] === 'others') {
53374                     if (hasMatch) continue;
53375
53376                     // Multipolygon members:
53377                     // If an entity...
53378                     //   1. is a way that hasn't matched other 'interesting' feature rules,
53379                     //   2. and it belongs to a single parent multipolygon relation
53380                     // ...then match whatever feature rules the parent multipolygon has matched.
53381                     // see #2548, #2887
53382                     //
53383                     // IMPORTANT:
53384                     // For this to work, getMatches must be called on relations before ways.
53385                     //
53386                     if (entity.type === 'way') {
53387                         var parents = features.getParents(entity, resolver, geometry);
53388                         if (parents.length === 1 && parents[0].isMultipolygon()) {
53389                             var pkey = osmEntity$$1.key(parents[0]);
53390                             if (_cache[pkey] && _cache[pkey].matches) {
53391                                 matches = lodash.clone(_cache[pkey].matches);
53392                                 continue;
53393                             }
53394                         }
53395                     }
53396                 }
53397
53398                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
53399                     matches[_keys[i]] = hasMatch = true;
53400                 }
53401             }
53402             _cache[ent].matches = matches;
53403         }
53404
53405         return _cache[ent].matches;
53406     };
53407
53408
53409     features.getParents = function(entity, resolver, geometry) {
53410         if (geometry === 'point') return [];
53411
53412         var ent = osmEntity$$1.key(entity);
53413         if (!_cache[ent]) {
53414             _cache[ent] = {};
53415         }
53416
53417         if (!_cache[ent].parents) {
53418             var parents = [];
53419             if (geometry === 'vertex') {
53420                 parents = resolver.parentWays(entity);
53421             } else {   // 'line', 'area', 'relation'
53422                 parents = resolver.parentRelations(entity);
53423             }
53424             _cache[ent].parents = parents;
53425         }
53426         return _cache[ent].parents;
53427     };
53428
53429
53430     features.isHiddenFeature = function(entity, resolver, geometry) {
53431         if (!_hidden.length) return false;
53432         if (!entity.version) return false;
53433
53434         var matches = features.getMatches(entity, resolver, geometry);
53435
53436         for (var i = 0; i < _hidden.length; i++) {
53437             if (matches[_hidden[i]]) return true;
53438         }
53439         return false;
53440     };
53441
53442
53443     features.isHiddenChild = function(entity, resolver, geometry) {
53444         if (!_hidden.length) return false;
53445         if (!entity.version || geometry === 'point') return false;
53446
53447         var parents = features.getParents(entity, resolver, geometry);
53448         if (!parents.length) return false;
53449
53450         for (var i = 0; i < parents.length; i++) {
53451             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
53452                 return false;
53453             }
53454         }
53455         return true;
53456     };
53457
53458
53459     features.hasHiddenConnections = function(entity, resolver) {
53460         if (!_hidden.length) return false;
53461         var childNodes, connections;
53462
53463         if (entity.type === 'midpoint') {
53464             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
53465             connections = [];
53466         } else {
53467             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
53468             connections = features.getParents(entity, resolver, entity.geometry(resolver));
53469         }
53470
53471         // gather ways connected to child nodes..
53472         connections = lodash.reduce(childNodes, function(result, e) {
53473             return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
53474         }, connections);
53475
53476         return connections.length ? lodash.some(connections, function(e) {
53477             return features.isHidden(e, resolver, e.geometry(resolver));
53478         }) : false;
53479     };
53480
53481
53482     features.isHidden = function(entity, resolver, geometry) {
53483         if (!_hidden.length) return false;
53484         if (!entity.version) return false;
53485
53486         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
53487         return fn(entity, resolver, geometry);
53488     };
53489
53490
53491     features.filter = function(d, resolver) {
53492         if (!_hidden.length) return d;
53493
53494         var result = [];
53495         for (var i = 0; i < d.length; i++) {
53496             var entity = d[i];
53497             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
53498                 result.push(entity);
53499             }
53500         }
53501         return result;
53502     };
53503
53504
53505     return utilRebind(features, dispatch$$1, 'on');
53506 }
53507
53508 function utilBindOnce(target, type, listener, capture) {
53509     var typeOnce = type + '.once';
53510     function one() {
53511         target.on(typeOnce, null);
53512         listener.apply(this, arguments);
53513     }
53514     target.on(typeOnce, one, capture);
53515     return this;
53516 }
53517
53518 function rendererMap(context) {
53519
53520     var dimensions = [1, 1],
53521         dispatch$$1 = dispatch('move', 'drawn'),
53522         projection = context.projection,
53523         dblclickEnabled = true,
53524         redrawEnabled = true,
53525         transformStart = projection.transform(),
53526         transformed = false,
53527         minzoom = 0,
53528         drawLayers = svgLayers(projection, context),
53529         drawPoints = svgPoints$$1(projection, context),
53530         drawVertices = svgVertices$$1(projection, context),
53531         drawLines = svgLines$$1(projection),
53532         drawAreas = svgAreas$$1(projection, context),
53533         drawMidpoints = svgMidpoints$$1(projection, context),
53534         drawLabels = svgLabels(projection, context),
53535         supersurface = select(null),
53536         wrapper = select(null),
53537         surface = select(null),
53538         mouse$$1,
53539         mousemove;
53540
53541     var zoom$$1 = zoom()
53542             .scaleExtent([ztok(2), ztok(24)])
53543             .interpolate(interpolate)
53544             .filter(zoomEventFilter)
53545             .on('zoom', zoomPan);
53546
53547     var _selection = select(null);
53548
53549
53550     function map$$1(selection$$1) {
53551
53552         _selection = selection$$1;
53553
53554         context
53555             .on('change.map', immediateRedraw);
53556
53557         context.connection()
53558             .on('change.map', immediateRedraw);
53559
53560         context.history()
53561             .on('change.map', immediateRedraw)
53562             .on('undone.context redone.context', function(stack$$1) {
53563                 var followSelected = false;
53564                 if (Array.isArray(stack$$1.selectedIDs)) {
53565                     followSelected = (stack$$1.selectedIDs.length === 1 && stack$$1.selectedIDs[0][0] === 'n');
53566                     context.enter(
53567                         modeSelect(context, stack$$1.selectedIDs).suppressMenu(true).follow(followSelected)
53568                     );
53569                 }
53570                 if (!followSelected && stack$$1.transform) {
53571                     map$$1.transformEase(stack$$1.transform);
53572                 }
53573             });
53574
53575         context.background()
53576             .on('change.map', immediateRedraw);
53577
53578         context.features()
53579             .on('redraw.map', immediateRedraw);
53580
53581         drawLayers
53582             .on('change.map', function() {
53583                 context.background().updateImagery();
53584                 immediateRedraw();
53585             });
53586
53587         selection$$1
53588             .on('dblclick.map', dblClick)
53589             .call(zoom$$1, projection.transform());
53590
53591         supersurface = selection$$1.append('div')
53592             .attr('id', 'supersurface')
53593             .call(utilSetTransform, 0, 0);
53594
53595         // Need a wrapper div because Opera can't cope with an absolutely positioned
53596         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
53597         wrapper = supersurface
53598             .append('div')
53599             .attr('class', 'layer layer-data');
53600
53601         map$$1.surface = surface = wrapper
53602             .call(drawLayers)
53603             .selectAll('.surface')
53604             .attr('id', 'surface');
53605
53606         surface
53607             .call(drawLabels.observe)
53608             .on('mousedown.zoom', function() {
53609                 if (event.button === 2) {
53610                     event.stopPropagation();
53611                 }
53612             }, true)
53613             .on('mouseup.zoom', function() {
53614                 if (resetTransform()) immediateRedraw();
53615             })
53616             .on('mousemove.map', function() {
53617                 mousemove = event;
53618             })
53619             .on('mouseover.vertices', function() {
53620                 if (map$$1.editable() && !transformed) {
53621                     var hover = event.target.__data__;
53622                     surface.selectAll('.data-layer-osm')
53623                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
53624                     dispatch$$1.call('drawn', this, {full: false});
53625                 }
53626             })
53627             .on('mouseout.vertices', function() {
53628                 if (map$$1.editable() && !transformed) {
53629                     var hover = event.relatedTarget && event.relatedTarget.__data__;
53630                     surface.selectAll('.data-layer-osm')
53631                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
53632                     dispatch$$1.call('drawn', this, {full: false});
53633                 }
53634             });
53635
53636         supersurface
53637             .call(context.background());
53638
53639         context.on('enter.map', function() {
53640             if (map$$1.editable() && !transformed) {
53641                 var all = context.intersects(map$$1.extent()),
53642                     filter = utilFunctor(true),
53643                     graph = context.graph();
53644
53645                 all = context.features().filter(all, graph);
53646                 surface.selectAll('.data-layer-osm')
53647                     .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
53648                     .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
53649                 dispatch$$1.call('drawn', this, {full: false});
53650             }
53651         });
53652
53653         map$$1.dimensions(utilGetDimensions(selection$$1));
53654     }
53655
53656
53657     function zoomEventFilter() {
53658         // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
53659         // Intercept `mousedown` and check if there is an orphaned zoom gesture.
53660         // This can happen if a previous `mousedown` occurred without a `mouseup`.
53661         // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
53662         // so that d3-zoom won't stop propagation of new `mousedown` events.
53663         if (event.type === 'mousedown') {
53664             var hasOrphan = false;
53665             var listeners = window.__on;
53666             for (var i = 0; i < listeners.length; i++) {
53667                 var listener = listeners[i];
53668                 if (listener.name === 'zoom' && listener.type === 'mouseup') {
53669                     hasOrphan = true;
53670                     break;
53671                 }
53672             }
53673             if (hasOrphan) {
53674                 var event$$1 = window.CustomEvent;
53675                 if (event$$1) {
53676                     event$$1 = new event$$1('mouseup');
53677                 } else {
53678                     event$$1 = window.document.createEvent('Event');
53679                     event$$1.initEvent('mouseup', false, false);
53680                 }
53681                 // Event needs to be dispatched with an event.view property.
53682                 event$$1.view = window;
53683                 window.dispatchEvent(event$$1);
53684             }
53685         }
53686
53687         return event.button !== 2;   // ignore right clicks
53688     }
53689
53690
53691     function ztok(z) {
53692         return 256 * Math.pow(2, z);
53693     }
53694
53695     function ktoz(k) {
53696         return Math.max(Math.log(k) / Math.LN2 - 8, 0);
53697     }
53698
53699     function pxCenter() {
53700         return [dimensions[0] / 2, dimensions[1] / 2];
53701     }
53702
53703
53704     function drawVector(difference, extent$$1) {
53705         var graph = context.graph(),
53706             features = context.features(),
53707             all = context.intersects(map$$1.extent()),
53708             data, filter;
53709
53710         if (difference) {
53711             var complete = difference.complete(map$$1.extent());
53712             data = lodash.compact(lodash.values(complete));
53713             filter = function(d) { return d.id in complete; };
53714             features.clear(data);
53715
53716         } else {
53717             // force a full redraw if gatherStats detects that a feature
53718             // should be auto-hidden (e.g. points or buildings)..
53719             if (features.gatherStats(all, graph, dimensions)) {
53720                 extent$$1 = undefined;
53721             }
53722
53723             if (extent$$1) {
53724                 data = context.intersects(map$$1.extent().intersection(extent$$1));
53725                 var set$$1 = set(lodash.map(data, 'id'));
53726                 filter = function(d) { return set$$1.has(d.id); };
53727
53728             } else {
53729                 data = all;
53730                 filter = utilFunctor(true);
53731             }
53732         }
53733
53734         data = features.filter(data, graph);
53735
53736         surface.selectAll('.data-layer-osm')
53737             .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
53738             .call(drawLines, graph, data, filter)
53739             .call(drawAreas, graph, data, filter)
53740             .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
53741             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
53742             .call(drawPoints, graph, data, filter);
53743
53744         dispatch$$1.call('drawn', this, {full: true});
53745     }
53746
53747
53748     function editOff() {
53749         context.features().resetStats();
53750         surface.selectAll('.layer-osm *').remove();
53751         dispatch$$1.call('drawn', this, {full: true});
53752     }
53753
53754
53755     function dblClick() {
53756         if (!dblclickEnabled) {
53757             event.preventDefault();
53758             event.stopImmediatePropagation();
53759         }
53760     }
53761
53762
53763     function zoomPan(manualEvent) {
53764         var eventTransform = (manualEvent || event).transform;
53765
53766         if (transformStart.x === eventTransform.x &&
53767             transformStart.y === eventTransform.y &&
53768             transformStart.k === eventTransform.k) {
53769             return;  // no change
53770         }
53771
53772         if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
53773             surface.interrupt();
53774             uiFlash(context.container())
53775                 .select('.content')
53776                 .text(t('cannot_zoom'));
53777             setZoom(context.minEditableZoom(), true);
53778             queueRedraw();
53779             dispatch$$1.call('move', this, map$$1);
53780             return;
53781         }
53782
53783         projection.transform(eventTransform);
53784
53785         var scale = eventTransform.k / transformStart.k,
53786             tX = (eventTransform.x / scale - transformStart.x) * scale,
53787             tY = (eventTransform.y / scale - transformStart.y) * scale;
53788
53789         transformed = true;
53790         utilSetTransform(supersurface, tX, tY, scale);
53791         queueRedraw();
53792
53793         dispatch$$1.call('move', this, map$$1);
53794     }
53795
53796
53797     function resetTransform() {
53798         if (!transformed) return false;
53799
53800         surface.selectAll('.radial-menu').interrupt().remove();
53801         utilSetTransform(supersurface, 0, 0);
53802         transformed = false;
53803         return true;
53804     }
53805
53806
53807     function redraw(difference, extent$$1) {
53808         if (surface.empty() || !redrawEnabled) return;
53809
53810         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
53811         // It would result in artifacts where differenced entities are redrawn with
53812         // one transform and unchanged entities with another.
53813         if (resetTransform()) {
53814             difference = extent$$1 = undefined;
53815         }
53816
53817         var z = String(~~map$$1.zoom());
53818         if (surface.attr('data-zoom') !== z) {
53819             surface.attr('data-zoom', z)
53820                 .classed('low-zoom', z <= 16);
53821         }
53822
53823         if (!difference) {
53824             supersurface.call(context.background());
53825         }
53826
53827         wrapper
53828             .call(drawLayers);
53829
53830         // OSM
53831         if (map$$1.editable()) {
53832             context.loadTiles(projection, dimensions);
53833             drawVector(difference, extent$$1);
53834         } else {
53835             editOff();
53836         }
53837
53838         transformStart = projection.transform();
53839
53840         return map$$1;
53841     }
53842
53843
53844     var queueRedraw = lodash.throttle(redraw, 750);
53845
53846
53847     var immediateRedraw = function(difference, extent$$1) {
53848         if (!difference && !extent$$1) queueRedraw.cancel();
53849         redraw(difference, extent$$1);
53850     };
53851
53852
53853     function pointLocation(p) {
53854         var translate = projection.translate(),
53855             scale = projection.scale() * 2 * Math.PI;
53856         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
53857     }
53858
53859
53860     function locationPoint(l) {
53861         var translate = projection.translate(),
53862             scale = projection.scale() * 2 * Math.PI;
53863         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
53864     }
53865
53866
53867     map$$1.mouse = function() {
53868         var event$$1 = mousemove || event;
53869         if (event$$1) {
53870             var s;
53871             while ((s = event$$1.sourceEvent)) { event$$1 = s; }
53872             return mouse$$1(event$$1);
53873         }
53874         return null;
53875     };
53876
53877
53878     map$$1.mouseCoordinates = function() {
53879         return projection.invert(map$$1.mouse());
53880     };
53881
53882
53883     map$$1.dblclickEnable = function(_) {
53884         if (!arguments.length) return dblclickEnabled;
53885         dblclickEnabled = _;
53886         return map$$1;
53887     };
53888
53889
53890     map$$1.redrawEnable = function(_) {
53891         if (!arguments.length) return redrawEnabled;
53892         redrawEnabled = _;
53893         return map$$1;
53894     };
53895
53896
53897     function setTransform(t2, duration, force) {
53898         var t$$1 = projection.transform();
53899         if (!force && t2.k === t$$1.k && t2.x === t$$1.x && t2.y === t$$1.y) {
53900             return false;
53901         }
53902
53903         if (duration) {
53904             _selection
53905                 .transition()
53906                 .duration(duration)
53907                 .on('start', function() { map$$1.startEase(); })
53908                 .call(zoom$$1.transform, identity$6.translate(t2.x, t2.y).scale(t2.k));
53909         } else {
53910             projection.transform(t2);
53911             transformStart = t2;
53912             _selection.call(zoom$$1.transform, transformStart);
53913         }
53914     }
53915
53916
53917     function setZoom(z2, force, duration) {
53918         if (z2 === map$$1.zoom() && !force) {
53919             return false;
53920         }
53921
53922         var k = projection.scale(),
53923             k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
53924             center = pxCenter(),
53925             l = pointLocation(center);
53926
53927         projection.scale(k2);
53928
53929         var t$$1 = projection.translate();
53930         l = locationPoint(l);
53931
53932         t$$1[0] += center[0] - l[0];
53933         t$$1[1] += center[1] - l[1];
53934
53935         if (duration) {
53936             projection.scale(k);  // reset scale
53937             _selection
53938                 .transition()
53939                 .duration(duration)
53940                 .on('start', function() { map$$1.startEase(); })
53941                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k2));
53942         } else {
53943             projection.translate(t$$1);
53944             transformStart = projection.transform();
53945             _selection.call(zoom$$1.transform, transformStart);
53946         }
53947
53948         return true;
53949     }
53950
53951
53952     function setCenter(loc2, duration) {
53953         var c = map$$1.center();
53954         if (loc2[0] === c[0] && loc2[1] === c[1]) {
53955             return false;
53956         }
53957
53958         var t$$1 = projection.translate(),
53959             k = projection.scale(),
53960             pxC = pxCenter(),
53961             ll = projection(loc2);
53962
53963         t$$1[0] = t$$1[0] - ll[0] + pxC[0];
53964         t$$1[1] = t$$1[1] - ll[1] + pxC[1];
53965
53966         if (duration) {
53967             _selection
53968                 .transition()
53969                 .duration(duration)
53970                 .on('start', function() { map$$1.startEase(); })
53971                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k));
53972         } else {
53973             projection.translate(t$$1);
53974             transformStart = projection.transform();
53975             _selection.call(zoom$$1.transform, transformStart);
53976         }
53977
53978         return true;
53979     }
53980
53981
53982     map$$1.pan = function(delta, duration) {
53983         var t$$1 = projection.translate(),
53984             k = projection.scale();
53985
53986         t$$1[0] += delta[0];
53987         t$$1[1] += delta[1];
53988
53989         if (duration) {
53990             _selection
53991                 .transition()
53992                 .duration(duration)
53993                 .on('start', function() { map$$1.startEase(); })
53994                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k));
53995         } else {
53996             projection.translate(t$$1);
53997             transformStart = projection.transform();
53998             _selection.call(zoom$$1.transform, transformStart);
53999             dispatch$$1.call('move', this, map$$1);
54000             immediateRedraw();
54001         }
54002
54003         return map$$1;
54004     };
54005
54006
54007     map$$1.dimensions = function(_) {
54008         if (!arguments.length) return dimensions;
54009         var center = map$$1.center();
54010         dimensions = _;
54011         drawLayers.dimensions(dimensions);
54012         context.background().dimensions(dimensions);
54013         projection.clipExtent([[0, 0], dimensions]);
54014         mouse$$1 = utilFastMouse(supersurface.node());
54015         setCenter(center);
54016
54017         queueRedraw();
54018         return map$$1;
54019     };
54020
54021
54022     function zoomIn(delta) {
54023         setZoom(~~map$$1.zoom() + delta, true, 250);
54024     }
54025
54026     function zoomOut(delta) {
54027         setZoom(~~map$$1.zoom() - delta, true, 250);
54028     }
54029
54030     map$$1.zoomIn = function() { zoomIn(1); };
54031     map$$1.zoomInFurther = function() { zoomIn(4); };
54032
54033     map$$1.zoomOut = function() { zoomOut(1); };
54034     map$$1.zoomOutFurther = function() { zoomOut(4); };
54035
54036
54037     map$$1.center = function(loc2) {
54038         if (!arguments.length) {
54039             return projection.invert(pxCenter());
54040         }
54041
54042         if (setCenter(loc2)) {
54043             dispatch$$1.call('move', this, map$$1);
54044         }
54045
54046         queueRedraw();
54047         return map$$1;
54048     };
54049
54050
54051     map$$1.zoom = function(z2) {
54052         if (!arguments.length) {
54053             return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
54054         }
54055
54056         if (z2 < minzoom) {
54057             surface.interrupt();
54058             uiFlash(context.container())
54059                 .select('.content')
54060                 .text(t('cannot_zoom'));
54061             z2 = context.minEditableZoom();
54062         }
54063
54064         if (setZoom(z2)) {
54065             dispatch$$1.call('move', this, map$$1);
54066         }
54067
54068         queueRedraw();
54069         return map$$1;
54070     };
54071
54072
54073     map$$1.zoomTo = function(entity, zoomLimits) {
54074         var extent$$1 = entity.extent(context.graph());
54075         if (!isFinite(extent$$1.area())) return;
54076
54077         var z2 = map$$1.trimmedExtentZoom(extent$$1);
54078         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
54079         map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
54080     };
54081
54082
54083     map$$1.centerZoom = function(loc2, z2) {
54084         var centered = setCenter(loc2),
54085             zoomed   = setZoom(z2);
54086
54087         if (centered || zoomed) {
54088             dispatch$$1.call('move', this, map$$1);
54089         }
54090
54091         queueRedraw();
54092         return map$$1;
54093     };
54094
54095
54096     map$$1.centerEase = function(loc2, duration) {
54097         duration = duration || 250;
54098         setCenter(loc2, duration);
54099         return map$$1;
54100     };
54101
54102
54103     map$$1.zoomEase = function(z2, duration) {
54104         duration = duration || 250;
54105         setZoom(z2, false, duration);
54106         return map$$1;
54107     };
54108
54109
54110     map$$1.transformEase = function(t2, duration) {
54111         duration = duration || 250;
54112         setTransform(t2, duration, false);
54113         return map$$1;
54114     };
54115
54116
54117     map$$1.startEase = function() {
54118         utilBindOnce(surface, 'mousedown.ease', function() {
54119             map$$1.cancelEase();
54120         });
54121         return map$$1;
54122     };
54123
54124
54125     map$$1.cancelEase = function() {
54126         _selection.interrupt();
54127         return map$$1;
54128     };
54129
54130
54131     map$$1.extent = function(_) {
54132         if (!arguments.length) {
54133             return new geoExtent$$1(projection.invert([0, dimensions[1]]),
54134                                  projection.invert([dimensions[0], 0]));
54135         } else {
54136             var extent$$1 = geoExtent$$1(_);
54137             map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
54138         }
54139     };
54140
54141
54142     map$$1.trimmedExtent = function(_) {
54143         if (!arguments.length) {
54144             var headerY = 60, footerY = 30, pad = 10;
54145             return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
54146                                  projection.invert([dimensions[0] - pad, headerY + pad]));
54147         } else {
54148             var extent$$1 = geoExtent$$1(_);
54149             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
54150         }
54151     };
54152
54153
54154     function calcZoom(extent$$1, dim) {
54155         var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
54156             br = projection([extent$$1[1][0], extent$$1[0][1]]);
54157
54158         // Calculate maximum zoom that fits extent
54159         var hFactor = (br[0] - tl[0]) / dim[0],
54160             vFactor = (br[1] - tl[1]) / dim[1],
54161             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
54162             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
54163             newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
54164
54165         return newZoom;
54166     }
54167
54168
54169     map$$1.extentZoom = function(_) {
54170         return calcZoom(geoExtent$$1(_), dimensions);
54171     };
54172
54173
54174     map$$1.trimmedExtentZoom = function(_) {
54175         var trimY = 120, trimX = 40,
54176             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
54177         return calcZoom(geoExtent$$1(_), trimmed);
54178     };
54179
54180
54181     map$$1.editable = function() {
54182         return map$$1.zoom() >= context.minEditableZoom();
54183     };
54184
54185
54186     map$$1.minzoom = function(_) {
54187         if (!arguments.length) return minzoom;
54188         minzoom = _;
54189         return map$$1;
54190     };
54191
54192
54193     map$$1.layers = drawLayers;
54194
54195
54196     return utilRebind(map$$1, dispatch$$1, 'on');
54197 }
54198
54199 var TAU = 2 * Math.PI;
54200 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
54201 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
54202 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
54203 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
54204
54205
54206 function uiMapInMap(context) {
54207     var key = '/';
54208
54209
54210     function map_in_map(selection$$1) {
54211         var backgroundLayer = rendererTileLayer(context),
54212             overlayLayers = {},
54213             projection = geoRawMercator(),
54214             gpxLayer = svgGpx(projection, context).showLabels(false),
54215             debugLayer = svgDebug(projection, context),
54216             zoom$$1 = zoom()
54217                 .scaleExtent([ztok(0.5), ztok(24)])
54218                 .on('start', zoomStarted)
54219                 .on('zoom', zoomed)
54220                 .on('end', zoomEnded),
54221             isTransformed = false,
54222             isHidden = true,
54223             skipEvents = false,
54224             gesture = null,
54225             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
54226             wrap = select(null),
54227             tiles = select(null),
54228             viewport = select(null),
54229             tStart,  // transform at start of gesture
54230             tCurr,   // transform at most recent event
54231             timeoutId;
54232
54233
54234         function zoomStarted() {
54235             if (skipEvents) return;
54236             tStart = tCurr = projection.transform();
54237             gesture = null;
54238         }
54239
54240
54241         function zoomed() {
54242             if (skipEvents) return;
54243
54244             var x = event.transform.x,
54245                 y = event.transform.y,
54246                 k = event.transform.k,
54247                 isZooming = (k !== tStart.k),
54248                 isPanning = (x !== tStart.x || y !== tStart.y);
54249
54250             if (!isZooming && !isPanning) {
54251                 return;  // no change
54252             }
54253
54254             // lock in either zooming or panning, don't allow both in minimap.
54255             if (!gesture) {
54256                 gesture = isZooming ? 'zoom' : 'pan';
54257             }
54258
54259             var tMini = projection.transform(),
54260                 tX, tY, scale;
54261
54262             if (gesture === 'zoom') {
54263                 var dMini = utilGetDimensions(wrap),
54264                     cMini = vecScale(dMini, 0.5);
54265                 scale = k / tMini.k;
54266                 tX = (cMini[0] / scale - cMini[0]) * scale;
54267                 tY = (cMini[1] / scale - cMini[1]) * scale;
54268             } else {
54269                 k = tMini.k;
54270                 scale = 1;
54271                 tX = x - tMini.x;
54272                 tY = y - tMini.y;
54273             }
54274
54275             utilSetTransform(tiles, tX, tY, scale);
54276             utilSetTransform(viewport, 0, 0, scale);
54277             isTransformed = true;
54278             tCurr = identity$6.translate(x, y).scale(k);
54279
54280             var zMain = ktoz(context.projection.scale()),
54281                 zMini = ktoz(k);
54282
54283             zDiff = zMain - zMini;
54284
54285             queueRedraw();
54286         }
54287
54288
54289         function zoomEnded() {
54290             if (skipEvents) return;
54291             if (gesture !== 'pan') return;
54292
54293             updateProjection();
54294             gesture = null;
54295             var dMini = utilGetDimensions(wrap),
54296                 cMini = vecScale(dMini, 0.5);
54297             context.map().center(projection.invert(cMini));   // recenter main map..
54298         }
54299
54300
54301         function updateProjection() {
54302             var loc = context.map().center(),
54303                 dMini = utilGetDimensions(wrap),
54304                 cMini = vecScale(dMini, 0.5),
54305                 tMain = context.projection.transform(),
54306                 zMain = ktoz(tMain.k),
54307                 zMini = Math.max(zMain - zDiff, 0.5),
54308                 kMini = ztok(zMini);
54309
54310             projection
54311                 .translate([tMain.x, tMain.y])
54312                 .scale(kMini);
54313
54314             var point = projection(loc),
54315                 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
54316                 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
54317                 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
54318
54319             projection
54320                 .translate([xMini, yMini])
54321                 .clipExtent([[0, 0], dMini]);
54322
54323             tCurr = projection.transform();
54324
54325             if (isTransformed) {
54326                 utilSetTransform(tiles, 0, 0);
54327                 utilSetTransform(viewport, 0, 0);
54328                 isTransformed = false;
54329             }
54330
54331             zoom$$1
54332                 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
54333
54334             skipEvents = true;
54335             wrap.call(zoom$$1.transform, tCurr);
54336             skipEvents = false;
54337         }
54338
54339
54340         function redraw() {
54341             clearTimeout(timeoutId);
54342             if (isHidden) return;
54343
54344             updateProjection();
54345
54346             var dMini = utilGetDimensions(wrap),
54347                 zMini = ktoz(projection.scale());
54348
54349             // setup tile container
54350             tiles = wrap
54351                 .selectAll('.map-in-map-tiles')
54352                 .data([0]);
54353
54354             tiles = tiles.enter()
54355                 .append('div')
54356                 .attr('class', 'map-in-map-tiles')
54357                 .merge(tiles);
54358
54359             // redraw background
54360             backgroundLayer
54361                 .source(context.background().baseLayerSource())
54362                 .projection(projection)
54363                 .dimensions(dMini);
54364
54365             var background = tiles
54366                 .selectAll('.map-in-map-background')
54367                 .data([0]);
54368
54369             background.enter()
54370                 .append('div')
54371                 .attr('class', 'map-in-map-background')
54372                 .merge(background)
54373                 .call(backgroundLayer);
54374
54375
54376             // redraw overlay
54377             var overlaySources = context.background().overlayLayerSources();
54378             var activeOverlayLayers = [];
54379             for (var i = 0; i < overlaySources.length; i++) {
54380                 if (overlaySources[i].validZoom(zMini)) {
54381                     if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
54382                     activeOverlayLayers.push(overlayLayers[i]
54383                         .source(overlaySources[i])
54384                         .projection(projection)
54385                         .dimensions(dMini));
54386                 }
54387             }
54388
54389             var overlay = tiles
54390                 .selectAll('.map-in-map-overlay')
54391                 .data([0]);
54392
54393             overlay = overlay.enter()
54394                 .append('div')
54395                 .attr('class', 'map-in-map-overlay')
54396                 .merge(overlay);
54397
54398
54399             var overlays = overlay
54400                 .selectAll('div')
54401                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
54402
54403             overlays.exit()
54404                 .remove();
54405
54406             overlays = overlays.enter()
54407                 .append('div')
54408                 .merge(overlays)
54409                 .each(function(layer) { select(this).call(layer); });
54410
54411
54412             var dataLayers = tiles
54413                 .selectAll('.map-in-map-data')
54414                 .data([0]);
54415
54416             dataLayers.exit()
54417                 .remove();
54418
54419             dataLayers = dataLayers.enter()
54420                 .append('svg')
54421                 .attr('class', 'map-in-map-data')
54422                 .merge(dataLayers)
54423                 .call(gpxLayer)
54424                 .call(debugLayer);
54425
54426
54427             // redraw viewport bounding box
54428             if (gesture !== 'pan') {
54429                 var getPath = index$5(projection),
54430                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
54431
54432                 viewport = wrap.selectAll('.map-in-map-viewport')
54433                     .data([0]);
54434
54435                 viewport = viewport.enter()
54436                     .append('svg')
54437                     .attr('class', 'map-in-map-viewport')
54438                     .merge(viewport);
54439
54440
54441                 var path$$1 = viewport.selectAll('.map-in-map-bbox')
54442                     .data([bbox]);
54443
54444                 path$$1.enter()
54445                     .append('path')
54446                     .attr('class', 'map-in-map-bbox')
54447                     .merge(path$$1)
54448                     .attr('d', getPath)
54449                     .classed('thick', function(d) { return getPath.area(d) < 30; });
54450             }
54451         }
54452
54453
54454         function queueRedraw() {
54455             clearTimeout(timeoutId);
54456             timeoutId = setTimeout(function() { redraw(); }, 750);
54457         }
54458
54459
54460         function toggle() {
54461             if (event) event.preventDefault();
54462
54463             isHidden = !isHidden;
54464
54465             var label = select('.minimap-toggle');
54466             label.classed('active', !isHidden)
54467                 .select('input').property('checked', !isHidden);
54468
54469             if (isHidden) {
54470                 wrap
54471                     .style('display', 'block')
54472                     .style('opacity', '1')
54473                     .transition()
54474                     .duration(200)
54475                     .style('opacity', '0')
54476                     .on('end', function() {
54477                         selection$$1.selectAll('.map-in-map')
54478                             .style('display', 'none');
54479                     });
54480             } else {
54481                 wrap
54482                     .style('display', 'block')
54483                     .style('opacity', '0')
54484                     .transition()
54485                     .duration(200)
54486                     .style('opacity', '1')
54487                     .on('end', function() {
54488                         redraw();
54489                     });
54490             }
54491         }
54492
54493
54494         uiMapInMap.toggle = toggle;
54495
54496         wrap = selection$$1.selectAll('.map-in-map')
54497             .data([0]);
54498
54499         wrap = wrap.enter()
54500             .append('div')
54501             .attr('class', 'map-in-map')
54502             .style('display', (isHidden ? 'none' : 'block'))
54503             .call(zoom$$1)
54504             .on('dblclick.zoom', null)
54505             .merge(wrap);
54506
54507         context.map()
54508             .on('drawn.map-in-map', function(drawn) {
54509                 if (drawn.full === true) {
54510                     redraw();
54511                 }
54512             });
54513
54514         redraw();
54515
54516         var keybinding = d3keybinding('map-in-map')
54517             .on(key, toggle);
54518
54519         select(document)
54520             .call(keybinding);
54521     }
54522
54523     return map_in_map;
54524 }
54525
54526 function uiTooltipHtml(text, key) {
54527     var s = '<span>' + text + '</span>';
54528     if (key) {
54529         s += '<div class="keyhint-wrap">' +
54530             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
54531             '<span class="keyhint"> ' + key + '</span></div>';
54532     }
54533     return s;
54534 }
54535
54536 function uiBackground(context) {
54537     var key = 'B',
54538         detected = utilDetect(),
54539         opacities = [1, 0.75, 0.5, 0.25],
54540         directions = [
54541             ['right', [0.5, 0]],
54542             ['top', [0, -0.5]],
54543             ['left', [-0.5, 0]],
54544             ['bottom', [0, 0.5]]],
54545         opacityDefault = (context.storage('background-opacity') !== null) ?
54546             (+context.storage('background-opacity')) : 1.0,
54547         customTemplate = context.storage('background-custom-template') || '',
54548         previous;
54549
54550     // Can be 0 from <1.3.0 use or due to issue #1923.
54551     if (opacityDefault === 0) opacityDefault = 1.0;
54552
54553
54554     function background(selection$$1) {
54555
54556         function sortSources(a, b) {
54557             return a.best() && !b.best() ? -1
54558                 : b.best() && !a.best() ? 1
54559                 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
54560         }
54561
54562
54563         function setOpacity(d) {
54564             var bg = context.container().selectAll('.layer-background')
54565                 .transition()
54566                 .style('opacity', d)
54567                 .attr('data-opacity', d);
54568
54569             if (!detected.opera) {
54570                 utilSetTransform(bg, 0, 0);
54571             }
54572
54573             opacityList.selectAll('li')
54574                 .classed('active', function(_) { return _ === d; });
54575
54576             context.storage('background-opacity', d);
54577         }
54578
54579
54580         function setTooltips(selection$$1) {
54581             selection$$1.each(function(d, i, nodes) {
54582                 var item = select(this).select('label'),
54583                     placement = (i < nodes.length / 2) ? 'bottom' : 'top';
54584
54585                 if (d === previous) {
54586                     item.call(tooltip()
54587                         .placement(placement)
54588                         .html(true)
54589                         .title(function() {
54590                             var tip = '<div>' + t('background.switch') + '</div>';
54591                             return uiTooltipHtml(tip, uiCmd('⌘B'));
54592                         })
54593                     );
54594                 } else if (d.description) {
54595                     item.call(tooltip()
54596                         .placement(placement)
54597                         .title(d.description)
54598                     );
54599                 } else {
54600                     item.call(tooltip().destroy);
54601                 }
54602             });
54603         }
54604
54605
54606         function selectLayer() {
54607             function active$$1(d) {
54608                 return context.background().showsLayer(d);
54609             }
54610
54611             content.selectAll('.layer, .custom_layer')
54612                 .classed('active', active$$1)
54613                 .classed('switch', function(d) { return d === previous; })
54614                 .call(setTooltips)
54615                 .selectAll('input')
54616                 .property('checked', active$$1);
54617         }
54618
54619
54620         function clickSetSource(d) {
54621             event.preventDefault();
54622             previous = context.background().baseLayerSource();
54623             context.background().baseLayerSource(d);
54624             selectLayer();
54625             document.activeElement.blur();
54626         }
54627
54628
54629         function editCustom() {
54630             event.preventDefault();
54631             var template = window.prompt(t('background.custom_prompt'), customTemplate);
54632             if (template) {
54633                 setCustom(template);
54634             } else {
54635                 selectLayer();
54636             }
54637         }
54638
54639
54640         function setCustom(template) {
54641             context.storage('background-custom-template', template);
54642             var d = rendererBackgroundSource.Custom(template);
54643             content.selectAll('.custom_layer').datum(d);
54644             clickSetSource(d);
54645         }
54646
54647
54648         function clickSetOverlay(d) {
54649             event.preventDefault();
54650             context.background().toggleOverlayLayer(d);
54651             selectLayer();
54652             document.activeElement.blur();
54653         }
54654
54655
54656         function drawList(layerList, type, change, filter) {
54657             var sources = context.background()
54658                 .sources(context.map().extent())
54659                 .filter(filter);
54660
54661             var layerLinks = layerList.selectAll('li.layer')
54662                 .data(sources, function(d) { return d.name(); });
54663
54664             layerLinks.exit()
54665                 .remove();
54666
54667             var enter = layerLinks.enter()
54668                 .insert('li', '.custom_layer')
54669                 .attr('class', 'layer')
54670                 .classed('best', function(d) { return d.best(); });
54671
54672             enter.filter(function(d) { return d.best(); })
54673                 .append('div')
54674                 .attr('class', 'best')
54675                 .call(tooltip()
54676                     .title(t('background.best_imagery'))
54677                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
54678                 .append('span')
54679                 .html('&#9733;');
54680
54681             var label = enter
54682                 .append('label');
54683
54684             label
54685                 .append('input')
54686                 .attr('type', type)
54687                 .attr('name', 'layers')
54688                 .on('change', change);
54689
54690             label
54691                 .append('span')
54692                 .text(function(d) { return d.name(); });
54693
54694
54695             layerList.selectAll('li.layer')
54696                 .sort(sortSources)
54697                 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
54698         }
54699
54700
54701         function update() {
54702             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
54703             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
54704
54705             selectLayer();
54706
54707             var source = context.background().baseLayerSource();
54708             if (source.id === 'custom') {
54709                 customTemplate = source.template;
54710             }
54711
54712             updateOffsetVal();
54713         }
54714
54715
54716         function updateOffsetVal() {
54717             var meters = geoOffsetToMeters(context.background().offset()),
54718                 x = +meters[0].toFixed(2),
54719                 y = +meters[1].toFixed(2);
54720
54721             selectAll('.nudge-inner-rect')
54722                 .select('input')
54723                 .classed('error', false)
54724                 .property('value', x + ', ' + y);
54725
54726             selectAll('.nudge-reset')
54727                 .classed('disabled', function() {
54728                     return (x === 0 && y === 0);
54729                 });
54730         }
54731
54732
54733         function resetOffset() {
54734             if (event.button !== 0) return;
54735             context.background().offset([0, 0]);
54736             updateOffsetVal();
54737         }
54738
54739
54740         function nudge(d) {
54741             context.background().nudge(d, context.map().zoom());
54742             updateOffsetVal();
54743         }
54744
54745
54746         function buttonOffset(d) {
54747             if (event.button !== 0) return;
54748             var timeout$$1 = window.setTimeout(function() {
54749                     interval$$1 = window.setInterval(nudge.bind(null, d), 100);
54750                 }, 500),
54751                 interval$$1;
54752
54753             function doneNudge() {
54754                 window.clearTimeout(timeout$$1);
54755                 window.clearInterval(interval$$1);
54756                 select(window)
54757                     .on('mouseup.buttonoffset', null, true)
54758                     .on('mousedown.buttonoffset', null, true);
54759             }
54760
54761             select(window)
54762                 .on('mouseup.buttonoffset', doneNudge, true)
54763                 .on('mousedown.buttonoffset', doneNudge, true);
54764
54765             nudge(d);
54766         }
54767
54768
54769         function inputOffset() {
54770             if (event.button !== 0) return;
54771             var input = select(this);
54772             var d = input.node().value;
54773
54774             if (d === '') return resetOffset();
54775
54776             d = d.replace(/;/g, ',').split(',').map(function(n) {
54777                 // if n is NaN, it will always get mapped to false.
54778                 return !isNaN(n) && n;
54779             });
54780
54781             if (d.length !== 2 || !d[0] || !d[1]) {
54782                 input.classed('error', true);
54783                 return;
54784             }
54785
54786             context.background().offset(geoMetersToOffset(d));
54787             updateOffsetVal();
54788         }
54789
54790
54791         function dragOffset() {
54792             if (event.button !== 0) return;
54793             var origin = [event.clientX, event.clientY];
54794
54795             context.container()
54796                 .append('div')
54797                 .attr('class', 'nudge-surface');
54798
54799             select(window)
54800                 .on('mousemove.offset', function() {
54801                     var latest = [event.clientX, event.clientY];
54802                     var d = [
54803                         -(origin[0] - latest[0]) / 4,
54804                         -(origin[1] - latest[1]) / 4
54805                     ];
54806
54807                     origin = latest;
54808                     nudge(d);
54809                 })
54810                 .on('mouseup.offset', function() {
54811                     if (event.button !== 0) return;
54812                     selectAll('.nudge-surface')
54813                         .remove();
54814
54815                     select(window)
54816                         .on('mousemove.offset', null)
54817                         .on('mouseup.offset', null);
54818                 });
54819
54820             event.preventDefault();
54821         }
54822
54823
54824         function hide() {
54825             setVisible(false);
54826         }
54827
54828
54829         function toggle() {
54830             if (event) event.preventDefault();
54831             tooltipBehavior.hide(button);
54832             setVisible(!button.classed('active'));
54833         }
54834
54835
54836         function quickSwitch() {
54837             if (previous) {
54838                 clickSetSource(previous);
54839             }
54840         }
54841
54842
54843         function setVisible(show) {
54844             if (show !== shown) {
54845                 button.classed('active', show);
54846                 shown = show;
54847
54848                 if (show) {
54849                     selection$$1.on('mousedown.background-inside', function() {
54850                         event.stopPropagation();
54851                     });
54852                     content
54853                         .style('display', 'block')
54854                         .style('right', '-300px')
54855                         .transition()
54856                         .duration(200)
54857                         .style('right', '0px');
54858                 } else {
54859                     content
54860                         .style('display', 'block')
54861                         .style('right', '0px')
54862                         .transition()
54863                         .duration(200)
54864                         .style('right', '-300px')
54865                         .on('end', function() {
54866                             select(this).style('display', 'none');
54867                         });
54868                     selection$$1.on('mousedown.background-inside', null);
54869                 }
54870             }
54871         }
54872
54873
54874         var content = selection$$1
54875                 .append('div')
54876                 .attr('class', 'fillL map-overlay col3 content hide'),
54877             tooltipBehavior = tooltip()
54878                 .placement((textDirection === 'rtl') ? 'right' : 'left')
54879                 .html(true)
54880                 .title(uiTooltipHtml(t('background.description'), key)),
54881             button = selection$$1
54882                 .append('button')
54883                 .attr('tabindex', -1)
54884                 .on('click', toggle)
54885                 .call(svgIcon('#icon-layers', 'light'))
54886                 .call(tooltipBehavior),
54887             shown = false;
54888
54889
54890         /* opacity switcher */
54891
54892         var opawrap = content
54893                 .append('div')
54894                 .attr('class', 'opacity-options-wrapper');
54895
54896         opawrap
54897             .append('h4')
54898             .text(t('background.title'));
54899
54900         var opacityList = opawrap
54901             .append('ul')
54902             .attr('class', 'opacity-options');
54903
54904         opacityList.selectAll('div.opacity')
54905             .data(opacities)
54906             .enter()
54907             .append('li')
54908             .attr('data-original-title', function(d) {
54909                 return t('background.percent_brightness', { opacity: (d * 100) });
54910             })
54911             .on('click.set-opacity', setOpacity)
54912             .html('<div class="select-box"></div>')
54913             .call(tooltip()
54914                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
54915             .append('div')
54916             .attr('class', 'opacity')
54917             .style('opacity', function(d) { return 1.25 - d; });
54918
54919
54920         /* background switcher */
54921
54922         var backgroundList = content
54923             .append('ul')
54924             .attr('class', 'layer-list')
54925             .attr('dir', 'auto');
54926
54927         var custom = backgroundList
54928             .append('li')
54929             .attr('class', 'custom_layer')
54930             .datum(rendererBackgroundSource.Custom());
54931
54932         custom
54933             .append('button')
54934             .attr('class', 'layer-browse')
54935             .call(tooltip()
54936                 .title(t('background.custom_button'))
54937                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
54938             .on('click', editCustom)
54939             .call(svgIcon('#icon-search'));
54940
54941         var label = custom
54942             .append('label');
54943
54944         label
54945             .append('input')
54946             .attr('type', 'radio')
54947             .attr('name', 'layers')
54948             .on('change', function () {
54949                 if (customTemplate) {
54950                     setCustom(customTemplate);
54951                 } else {
54952                     editCustom();
54953                 }
54954             });
54955
54956         label
54957             .append('span')
54958             .text(t('background.custom'));
54959
54960         content
54961             .append('div')
54962             .attr('class', 'imagery-faq')
54963             .append('a')
54964             .attr('target', '_blank')
54965             .attr('tabindex', -1)
54966             .call(svgIcon('#icon-out-link', 'inline'))
54967             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
54968             .append('span')
54969             .text(t('background.imagery_source_faq'));
54970
54971         var overlayList = content
54972             .append('ul')
54973             .attr('class', 'layer-list');
54974
54975         var controls = content
54976             .append('div')
54977             .attr('class', 'controls-list');
54978
54979
54980         /* minimap toggle */
54981
54982         var minimapLabel = controls
54983             .append('label')
54984             .call(tooltip()
54985                 .html(true)
54986                 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
54987                 .placement('top')
54988             );
54989
54990         minimapLabel
54991             .classed('minimap-toggle', true)
54992             .append('input')
54993             .attr('type', 'checkbox')
54994             .on('change', function() {
54995                 uiMapInMap.toggle();
54996                 event.preventDefault();
54997             });
54998
54999         minimapLabel
55000             .append('span')
55001             .text(t('background.minimap.description'));
55002
55003
55004         /* imagery offset controls */
55005
55006         var adjustments = content
55007             .append('div')
55008             .attr('class', 'adjustments');
55009
55010         adjustments
55011             .append('a')
55012             .text(t('background.fix_misalignment'))
55013             .attr('href', '#')
55014             .classed('hide-toggle', true)
55015             .classed('expanded', false)
55016             .on('click', function() {
55017                 if (event.button !== 0) return;
55018                 var exp = select(this).classed('expanded');
55019                 nudgeContainer.style('display', exp ? 'none' : 'block');
55020                 select(this).classed('expanded', !exp);
55021                 event.preventDefault();
55022             });
55023
55024         var nudgeContainer = adjustments
55025             .append('div')
55026             .attr('class', 'nudge-container cf')
55027             .style('display', 'none');
55028
55029         nudgeContainer
55030             .append('div')
55031             .attr('class', 'nudge-instructions')
55032             .text(t('background.offset'));
55033
55034         var nudgeRect = nudgeContainer
55035             .append('div')
55036             .attr('class', 'nudge-outer-rect')
55037             .on('mousedown', dragOffset);
55038
55039         nudgeRect
55040             .append('div')
55041             .attr('class', 'nudge-inner-rect')
55042             .append('input')
55043             .on('change', inputOffset)
55044             .on('mousedown', function() {
55045                 if (event.button !== 0) return;
55046                 event.stopPropagation();
55047             });
55048
55049         nudgeContainer
55050             .append('div')
55051             .selectAll('button')
55052             .data(directions).enter()
55053             .append('button')
55054             .attr('class', function(d) { return d[0] + ' nudge'; })
55055             .on('mousedown', function(d) {
55056                 if (event.button !== 0) return;
55057                 buttonOffset(d[1]);
55058             });
55059
55060         nudgeContainer
55061             .append('button')
55062             .attr('title', t('background.reset'))
55063             .attr('class', 'nudge-reset disabled')
55064             .on('click', resetOffset)
55065             .call(
55066                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
55067             );
55068
55069         context.map()
55070             .on('move.background-update', lodash.debounce(update, 1000));
55071
55072         context.background()
55073             .on('change.background-update', update);
55074
55075
55076         update();
55077         setOpacity(opacityDefault);
55078
55079         var keybinding = d3keybinding('background')
55080             .on(key, toggle)
55081             .on(uiCmd('⌘B'), quickSwitch)
55082             .on('F', hide)
55083             .on('H', hide);
55084
55085         select(document)
55086             .call(keybinding);
55087
55088         context.surface().on('mousedown.background-outside', hide);
55089         context.container().on('mousedown.background-outside', hide);
55090     }
55091
55092     return background;
55093 }
55094
55095 function uiContributors(context) {
55096     var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
55097         limit = 4,
55098         hidden = false,
55099         wrap = select(null);
55100
55101
55102     function update() {
55103         var users = {},
55104             entities = context.intersects(context.map().extent());
55105
55106         entities.forEach(function(entity) {
55107             if (entity && entity.user) users[entity.user] = true;
55108         });
55109
55110         var u = Object.keys(users),
55111             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
55112
55113         wrap.html('')
55114             .call(svgIcon('#icon-nearby', 'pre-text light'));
55115
55116         var userList = select(document.createElement('span'));
55117
55118         userList.selectAll()
55119             .data(subset)
55120             .enter()
55121             .append('a')
55122             .attr('class', 'user-link')
55123             .attr('href', function(d) { return context.connection().userURL(d); })
55124             .attr('target', '_blank')
55125             .attr('tabindex', -1)
55126             .text(String);
55127
55128         if (u.length > limit) {
55129             var count = select(document.createElement('span'));
55130
55131             count.append('a')
55132                 .attr('target', '_blank')
55133                 .attr('tabindex', -1)
55134                 .attr('href', function() {
55135                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
55136                 })
55137                 .text(u.length - limit + 1);
55138
55139             wrap.append('span')
55140                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
55141
55142         } else {
55143             wrap.append('span')
55144                 .html(t('contributors.list', { users: userList.html() }));
55145         }
55146
55147         if (!u.length) {
55148             hidden = true;
55149             wrap
55150                 .transition()
55151                 .style('opacity', 0);
55152
55153         } else if (hidden) {
55154             wrap
55155                 .transition()
55156                 .style('opacity', 1);
55157         }
55158     }
55159
55160
55161     return function(selection$$1) {
55162         wrap = selection$$1;
55163         update();
55164
55165         context.connection().on('loaded.contributors', debouncedUpdate);
55166         context.map().on('move.contributors', debouncedUpdate);
55167     };
55168 }
55169
55170 function uiFeatureInfo(context) {
55171     function update(selection$$1) {
55172         var features = context.features(),
55173             stats = features.stats(),
55174             count = 0,
55175             hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
55176                 if (stats[k]) {
55177                     count += stats[k];
55178                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
55179                 }
55180             }));
55181
55182         selection$$1.html('');
55183
55184         if (hiddenList.length) {
55185             var tooltipBehavior = tooltip()
55186                     .placement('top')
55187                     .html(true)
55188                     .title(function() {
55189                         return uiTooltipHtml(hiddenList.join('<br/>'));
55190                     });
55191
55192             var warning = selection$$1.append('a')
55193                 .attr('href', '#')
55194                 .attr('tabindex', -1)
55195                 .html(t('feature_info.hidden_warning', { count: count }))
55196                 .call(tooltipBehavior)
55197                 .on('click', function() {
55198                     tooltipBehavior.hide(warning);
55199                     // open map data panel?
55200                     event.preventDefault();
55201                 });
55202         }
55203
55204         selection$$1
55205             .classed('hide', !hiddenList.length);
55206     }
55207
55208
55209     return function(selection$$1) {
55210         update(selection$$1);
55211
55212         context.features().on('change.feature_info', function() {
55213             update(selection$$1);
55214         });
55215     };
55216 }
55217
55218 function uiFullScreen(context) {
55219     var element = context.container().node(),
55220         keybinding = d3keybinding('full-screen');
55221         // button;
55222
55223
55224     function getFullScreenFn() {
55225         if (element.requestFullscreen) {
55226             return element.requestFullscreen;
55227         } else if (element.msRequestFullscreen) {
55228             return element.msRequestFullscreen;
55229         } else if (element.mozRequestFullScreen) {
55230             return element.mozRequestFullScreen;
55231         } else if (element.webkitRequestFullscreen) {
55232             return element.webkitRequestFullscreen;
55233         }
55234     }
55235
55236
55237     function getExitFullScreenFn() {
55238         if (document.exitFullscreen) {
55239             return document.exitFullscreen;
55240         } else if (document.msExitFullscreen) {
55241             return document.msExitFullscreen;
55242         } else if (document.mozCancelFullScreen) {
55243             return document.mozCancelFullScreen;
55244         } else if (document.webkitExitFullscreen) {
55245             return document.webkitExitFullscreen;
55246         }
55247     }
55248
55249
55250     function isFullScreen() {
55251         return document.fullscreenElement ||
55252             document.mozFullScreenElement ||
55253             document.webkitFullscreenElement ||
55254             document.msFullscreenElement;
55255     }
55256
55257
55258     function isSupported() {
55259         return !!getFullScreenFn();
55260     }
55261
55262
55263     function fullScreen() {
55264         event.preventDefault();
55265         if (!isFullScreen()) {
55266             // button.classed('active', true);
55267             getFullScreenFn().apply(element);
55268         } else {
55269             // button.classed('active', false);
55270             getExitFullScreenFn().apply(document);
55271         }
55272     }
55273
55274
55275     return function() { // selection) {
55276         if (!isSupported())
55277             return;
55278
55279         // button = selection.append('button')
55280         //     .attr('title', t('full_screen'))
55281         //     .attr('tabindex', -1)
55282         //     .on('click', fullScreen)
55283         //     .call(tooltip);
55284
55285         // button.append('span')
55286         //     .attr('class', 'icon full-screen');
55287
55288         keybinding
55289             .on('f11', fullScreen)
55290             .on(uiCmd('⌘⇧F'), fullScreen);
55291
55292         select(document)
55293             .call(keybinding);
55294     };
55295 }
55296
55297 function uiModal(selection$$1, blocking) {
55298     var keybinding = d3keybinding('modal');
55299     var previous = selection$$1.select('div.modal');
55300     var animate = previous.empty();
55301
55302     previous.transition()
55303         .duration(200)
55304         .style('opacity', 0)
55305         .remove();
55306
55307     var shaded = selection$$1
55308         .append('div')
55309         .attr('class', 'shaded')
55310         .style('opacity', 0);
55311
55312     shaded.close = function() {
55313         shaded
55314             .transition()
55315             .duration(200)
55316             .style('opacity',0)
55317             .remove();
55318
55319         modal
55320             .transition()
55321             .duration(200)
55322             .style('top','0px');
55323
55324         keybinding.off();
55325     };
55326
55327
55328     var modal = shaded
55329         .append('div')
55330         .attr('class', 'modal fillL col6');
55331
55332     if (!blocking) {
55333         shaded.on('click.remove-modal', function() {
55334             if (event.target === this) {
55335                 shaded.close();
55336             }
55337         });
55338
55339         modal.append('button')
55340             .attr('class', 'close')
55341             .on('click', shaded.close)
55342             .call(svgIcon('#icon-close'));
55343
55344         keybinding
55345             .on('⌫', shaded.close)
55346             .on('⎋', shaded.close);
55347
55348         select(document)
55349             .call(keybinding);
55350     }
55351
55352     modal
55353         .append('div')
55354         .attr('class', 'content');
55355
55356     if (animate) {
55357         shaded.transition().style('opacity', 1);
55358     } else {
55359         shaded.style('opacity', 1);
55360     }
55361
55362
55363     return shaded;
55364 }
55365
55366 function uiLoading(context) {
55367     var message = '',
55368         blocking = false,
55369         modalSelection;
55370
55371
55372     var loading = function(selection) {
55373         modalSelection = uiModal(selection, blocking);
55374
55375         var loadertext = modalSelection.select('.content')
55376             .classed('loading-modal', true)
55377             .append('div')
55378             .attr('class', 'modal-section fillL');
55379
55380         loadertext
55381             .append('img')
55382             .attr('class', 'loader')
55383             .attr('src', context.imagePath('loader-white.gif'));
55384
55385         loadertext
55386             .append('h3')
55387             .text(message);
55388
55389         modalSelection.select('button.close')
55390             .attr('class', 'hide');
55391
55392         return loading;
55393     };
55394
55395
55396     loading.message = function(_) {
55397         if (!arguments.length) return message;
55398         message = _;
55399         return loading;
55400     };
55401
55402
55403     loading.blocking = function(_) {
55404         if (!arguments.length) return blocking;
55405         blocking = _;
55406         return loading;
55407     };
55408
55409
55410     loading.close = function() {
55411         modalSelection.remove();
55412     };
55413
55414
55415     return loading;
55416 }
55417
55418 function uiGeolocate(context) {
55419     var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
55420         locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
55421         timeoutId;
55422
55423
55424     function click() {
55425         context.enter(modeBrowse$$1(context));
55426         context.container().call(locating);
55427         navigator.geolocation.getCurrentPosition(success, error, geoOptions);
55428
55429         // This timeout ensures that we still call finish() even if
55430         // the user declines to share their location in Firefox
55431         timeoutId = setTimeout(finish, 10000 /* 10sec */ );
55432     }
55433
55434
55435     function success(position) {
55436         var map = context.map(),
55437             extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
55438                 .padByMeters(position.coords.accuracy);
55439
55440         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
55441         finish();
55442     }
55443
55444
55445     function error() {
55446         finish();
55447     }
55448
55449
55450     function finish() {
55451         locating.close();  // unblock ui
55452         if (timeoutId) { clearTimeout(timeoutId); }
55453         timeoutId = undefined;
55454     }
55455
55456
55457     return function(selection) {
55458         if (!navigator.geolocation) return;
55459
55460         selection
55461             .append('button')
55462             .attr('tabindex', -1)
55463             .attr('title', t('geolocate.title'))
55464             .on('click', click)
55465             .call(svgIcon('#icon-geolocate', 'light'))
55466             .call(tooltip()
55467                 .placement((textDirection === 'rtl') ? 'right' : 'left'));
55468     };
55469 }
55470
55471 var marked = createCommonjsModule(function (module, exports) {
55472 /**
55473  * marked - a markdown parser
55474  * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
55475  * https://github.com/chjj/marked
55476  */
55477
55478 (function() {
55479
55480 /**
55481  * Block-Level Grammar
55482  */
55483
55484 var block = {
55485   newline: /^\n+/,
55486   code: /^( {4}[^\n]+\n*)+/,
55487   fences: noop,
55488   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
55489   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
55490   nptable: noop,
55491   lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
55492   blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
55493   list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
55494   html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
55495   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
55496   table: noop,
55497   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
55498   text: /^[^\n]+/
55499 };
55500
55501 block.bullet = /(?:[*+-]|\d+\.)/;
55502 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
55503 block.item = replace(block.item, 'gm')
55504   (/bull/g, block.bullet)
55505   ();
55506
55507 block.list = replace(block.list)
55508   (/bull/g, block.bullet)
55509   ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
55510   ('def', '\\n+(?=' + block.def.source + ')')
55511   ();
55512
55513 block.blockquote = replace(block.blockquote)
55514   ('def', block.def)
55515   ();
55516
55517 block._tag = '(?!(?:'
55518   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
55519   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
55520   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
55521
55522 block.html = replace(block.html)
55523   ('comment', /<!--[\s\S]*?-->/)
55524   ('closed', /<(tag)[\s\S]+?<\/\1>/)
55525   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
55526   (/tag/g, block._tag)
55527   ();
55528
55529 block.paragraph = replace(block.paragraph)
55530   ('hr', block.hr)
55531   ('heading', block.heading)
55532   ('lheading', block.lheading)
55533   ('blockquote', block.blockquote)
55534   ('tag', '<' + block._tag)
55535   ('def', block.def)
55536   ();
55537
55538 /**
55539  * Normal Block Grammar
55540  */
55541
55542 block.normal = merge({}, block);
55543
55544 /**
55545  * GFM Block Grammar
55546  */
55547
55548 block.gfm = merge({}, block.normal, {
55549   fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
55550   paragraph: /^/,
55551   heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
55552 });
55553
55554 block.gfm.paragraph = replace(block.paragraph)
55555   ('(?!', '(?!'
55556     + block.gfm.fences.source.replace('\\1', '\\2') + '|'
55557     + block.list.source.replace('\\1', '\\3') + '|')
55558   ();
55559
55560 /**
55561  * GFM + Tables Block Grammar
55562  */
55563
55564 block.tables = merge({}, block.gfm, {
55565   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
55566   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
55567 });
55568
55569 /**
55570  * Block Lexer
55571  */
55572
55573 function Lexer(options) {
55574   this.tokens = [];
55575   this.tokens.links = {};
55576   this.options = options || marked.defaults;
55577   this.rules = block.normal;
55578
55579   if (this.options.gfm) {
55580     if (this.options.tables) {
55581       this.rules = block.tables;
55582     } else {
55583       this.rules = block.gfm;
55584     }
55585   }
55586 }
55587
55588 /**
55589  * Expose Block Rules
55590  */
55591
55592 Lexer.rules = block;
55593
55594 /**
55595  * Static Lex Method
55596  */
55597
55598 Lexer.lex = function(src, options) {
55599   var lexer = new Lexer(options);
55600   return lexer.lex(src);
55601 };
55602
55603 /**
55604  * Preprocessing
55605  */
55606
55607 Lexer.prototype.lex = function(src) {
55608   src = src
55609     .replace(/\r\n|\r/g, '\n')
55610     .replace(/\t/g, '    ')
55611     .replace(/\u00a0/g, ' ')
55612     .replace(/\u2424/g, '\n');
55613
55614   return this.token(src, true);
55615 };
55616
55617 /**
55618  * Lexing
55619  */
55620
55621 Lexer.prototype.token = function(src, top, bq) {
55622   var src = src.replace(/^ +$/gm, '')
55623     , next
55624     , loose
55625     , cap
55626     , bull
55627     , b
55628     , item
55629     , space
55630     , i
55631     , l;
55632
55633   while (src) {
55634     // newline
55635     if (cap = this.rules.newline.exec(src)) {
55636       src = src.substring(cap[0].length);
55637       if (cap[0].length > 1) {
55638         this.tokens.push({
55639           type: 'space'
55640         });
55641       }
55642     }
55643
55644     // code
55645     if (cap = this.rules.code.exec(src)) {
55646       src = src.substring(cap[0].length);
55647       cap = cap[0].replace(/^ {4}/gm, '');
55648       this.tokens.push({
55649         type: 'code',
55650         text: !this.options.pedantic
55651           ? cap.replace(/\n+$/, '')
55652           : cap
55653       });
55654       continue;
55655     }
55656
55657     // fences (gfm)
55658     if (cap = this.rules.fences.exec(src)) {
55659       src = src.substring(cap[0].length);
55660       this.tokens.push({
55661         type: 'code',
55662         lang: cap[2],
55663         text: cap[3] || ''
55664       });
55665       continue;
55666     }
55667
55668     // heading
55669     if (cap = this.rules.heading.exec(src)) {
55670       src = src.substring(cap[0].length);
55671       this.tokens.push({
55672         type: 'heading',
55673         depth: cap[1].length,
55674         text: cap[2]
55675       });
55676       continue;
55677     }
55678
55679     // table no leading pipe (gfm)
55680     if (top && (cap = this.rules.nptable.exec(src))) {
55681       src = src.substring(cap[0].length);
55682
55683       item = {
55684         type: 'table',
55685         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
55686         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
55687         cells: cap[3].replace(/\n$/, '').split('\n')
55688       };
55689
55690       for (i = 0; i < item.align.length; i++) {
55691         if (/^ *-+: *$/.test(item.align[i])) {
55692           item.align[i] = 'right';
55693         } else if (/^ *:-+: *$/.test(item.align[i])) {
55694           item.align[i] = 'center';
55695         } else if (/^ *:-+ *$/.test(item.align[i])) {
55696           item.align[i] = 'left';
55697         } else {
55698           item.align[i] = null;
55699         }
55700       }
55701
55702       for (i = 0; i < item.cells.length; i++) {
55703         item.cells[i] = item.cells[i].split(/ *\| */);
55704       }
55705
55706       this.tokens.push(item);
55707
55708       continue;
55709     }
55710
55711     // lheading
55712     if (cap = this.rules.lheading.exec(src)) {
55713       src = src.substring(cap[0].length);
55714       this.tokens.push({
55715         type: 'heading',
55716         depth: cap[2] === '=' ? 1 : 2,
55717         text: cap[1]
55718       });
55719       continue;
55720     }
55721
55722     // hr
55723     if (cap = this.rules.hr.exec(src)) {
55724       src = src.substring(cap[0].length);
55725       this.tokens.push({
55726         type: 'hr'
55727       });
55728       continue;
55729     }
55730
55731     // blockquote
55732     if (cap = this.rules.blockquote.exec(src)) {
55733       src = src.substring(cap[0].length);
55734
55735       this.tokens.push({
55736         type: 'blockquote_start'
55737       });
55738
55739       cap = cap[0].replace(/^ *> ?/gm, '');
55740
55741       // Pass `top` to keep the current
55742       // "toplevel" state. This is exactly
55743       // how markdown.pl works.
55744       this.token(cap, top, true);
55745
55746       this.tokens.push({
55747         type: 'blockquote_end'
55748       });
55749
55750       continue;
55751     }
55752
55753     // list
55754     if (cap = this.rules.list.exec(src)) {
55755       src = src.substring(cap[0].length);
55756       bull = cap[2];
55757
55758       this.tokens.push({
55759         type: 'list_start',
55760         ordered: bull.length > 1
55761       });
55762
55763       // Get each top-level item.
55764       cap = cap[0].match(this.rules.item);
55765
55766       next = false;
55767       l = cap.length;
55768       i = 0;
55769
55770       for (; i < l; i++) {
55771         item = cap[i];
55772
55773         // Remove the list item's bullet
55774         // so it is seen as the next token.
55775         space = item.length;
55776         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
55777
55778         // Outdent whatever the
55779         // list item contains. Hacky.
55780         if (~item.indexOf('\n ')) {
55781           space -= item.length;
55782           item = !this.options.pedantic
55783             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
55784             : item.replace(/^ {1,4}/gm, '');
55785         }
55786
55787         // Determine whether the next list item belongs here.
55788         // Backpedal if it does not belong in this list.
55789         if (this.options.smartLists && i !== l - 1) {
55790           b = block.bullet.exec(cap[i + 1])[0];
55791           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
55792             src = cap.slice(i + 1).join('\n') + src;
55793             i = l - 1;
55794           }
55795         }
55796
55797         // Determine whether item is loose or not.
55798         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
55799         // for discount behavior.
55800         loose = next || /\n\n(?!\s*$)/.test(item);
55801         if (i !== l - 1) {
55802           next = item.charAt(item.length - 1) === '\n';
55803           if (!loose) loose = next;
55804         }
55805
55806         this.tokens.push({
55807           type: loose
55808             ? 'loose_item_start'
55809             : 'list_item_start'
55810         });
55811
55812         // Recurse.
55813         this.token(item, false, bq);
55814
55815         this.tokens.push({
55816           type: 'list_item_end'
55817         });
55818       }
55819
55820       this.tokens.push({
55821         type: 'list_end'
55822       });
55823
55824       continue;
55825     }
55826
55827     // html
55828     if (cap = this.rules.html.exec(src)) {
55829       src = src.substring(cap[0].length);
55830       this.tokens.push({
55831         type: this.options.sanitize
55832           ? 'paragraph'
55833           : 'html',
55834         pre: !this.options.sanitizer
55835           && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
55836         text: cap[0]
55837       });
55838       continue;
55839     }
55840
55841     // def
55842     if ((!bq && top) && (cap = this.rules.def.exec(src))) {
55843       src = src.substring(cap[0].length);
55844       this.tokens.links[cap[1].toLowerCase()] = {
55845         href: cap[2],
55846         title: cap[3]
55847       };
55848       continue;
55849     }
55850
55851     // table (gfm)
55852     if (top && (cap = this.rules.table.exec(src))) {
55853       src = src.substring(cap[0].length);
55854
55855       item = {
55856         type: 'table',
55857         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
55858         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
55859         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
55860       };
55861
55862       for (i = 0; i < item.align.length; i++) {
55863         if (/^ *-+: *$/.test(item.align[i])) {
55864           item.align[i] = 'right';
55865         } else if (/^ *:-+: *$/.test(item.align[i])) {
55866           item.align[i] = 'center';
55867         } else if (/^ *:-+ *$/.test(item.align[i])) {
55868           item.align[i] = 'left';
55869         } else {
55870           item.align[i] = null;
55871         }
55872       }
55873
55874       for (i = 0; i < item.cells.length; i++) {
55875         item.cells[i] = item.cells[i]
55876           .replace(/^ *\| *| *\| *$/g, '')
55877           .split(/ *\| */);
55878       }
55879
55880       this.tokens.push(item);
55881
55882       continue;
55883     }
55884
55885     // top-level paragraph
55886     if (top && (cap = this.rules.paragraph.exec(src))) {
55887       src = src.substring(cap[0].length);
55888       this.tokens.push({
55889         type: 'paragraph',
55890         text: cap[1].charAt(cap[1].length - 1) === '\n'
55891           ? cap[1].slice(0, -1)
55892           : cap[1]
55893       });
55894       continue;
55895     }
55896
55897     // text
55898     if (cap = this.rules.text.exec(src)) {
55899       // Top-level should never reach here.
55900       src = src.substring(cap[0].length);
55901       this.tokens.push({
55902         type: 'text',
55903         text: cap[0]
55904       });
55905       continue;
55906     }
55907
55908     if (src) {
55909       throw new
55910         Error('Infinite loop on byte: ' + src.charCodeAt(0));
55911     }
55912   }
55913
55914   return this.tokens;
55915 };
55916
55917 /**
55918  * Inline-Level Grammar
55919  */
55920
55921 var inline = {
55922   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
55923   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
55924   url: noop,
55925   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
55926   link: /^!?\[(inside)\]\(href\)/,
55927   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
55928   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
55929   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
55930   em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
55931   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
55932   br: /^ {2,}\n(?!\s*$)/,
55933   del: noop,
55934   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
55935 };
55936
55937 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
55938 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
55939
55940 inline.link = replace(inline.link)
55941   ('inside', inline._inside)
55942   ('href', inline._href)
55943   ();
55944
55945 inline.reflink = replace(inline.reflink)
55946   ('inside', inline._inside)
55947   ();
55948
55949 /**
55950  * Normal Inline Grammar
55951  */
55952
55953 inline.normal = merge({}, inline);
55954
55955 /**
55956  * Pedantic Inline Grammar
55957  */
55958
55959 inline.pedantic = merge({}, inline.normal, {
55960   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
55961   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
55962 });
55963
55964 /**
55965  * GFM Inline Grammar
55966  */
55967
55968 inline.gfm = merge({}, inline.normal, {
55969   escape: replace(inline.escape)('])', '~|])')(),
55970   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
55971   del: /^~~(?=\S)([\s\S]*?\S)~~/,
55972   text: replace(inline.text)
55973     (']|', '~]|')
55974     ('|', '|https?://|')
55975     ()
55976 });
55977
55978 /**
55979  * GFM + Line Breaks Inline Grammar
55980  */
55981
55982 inline.breaks = merge({}, inline.gfm, {
55983   br: replace(inline.br)('{2,}', '*')(),
55984   text: replace(inline.gfm.text)('{2,}', '*')()
55985 });
55986
55987 /**
55988  * Inline Lexer & Compiler
55989  */
55990
55991 function InlineLexer(links, options) {
55992   this.options = options || marked.defaults;
55993   this.links = links;
55994   this.rules = inline.normal;
55995   this.renderer = this.options.renderer || new Renderer;
55996   this.renderer.options = this.options;
55997
55998   if (!this.links) {
55999     throw new
56000       Error('Tokens array requires a `links` property.');
56001   }
56002
56003   if (this.options.gfm) {
56004     if (this.options.breaks) {
56005       this.rules = inline.breaks;
56006     } else {
56007       this.rules = inline.gfm;
56008     }
56009   } else if (this.options.pedantic) {
56010     this.rules = inline.pedantic;
56011   }
56012 }
56013
56014 /**
56015  * Expose Inline Rules
56016  */
56017
56018 InlineLexer.rules = inline;
56019
56020 /**
56021  * Static Lexing/Compiling Method
56022  */
56023
56024 InlineLexer.output = function(src, links, options) {
56025   var inline = new InlineLexer(links, options);
56026   return inline.output(src);
56027 };
56028
56029 /**
56030  * Lexing/Compiling
56031  */
56032
56033 InlineLexer.prototype.output = function(src) {
56034   var out = ''
56035     , link
56036     , text
56037     , href
56038     , cap;
56039
56040   while (src) {
56041     // escape
56042     if (cap = this.rules.escape.exec(src)) {
56043       src = src.substring(cap[0].length);
56044       out += cap[1];
56045       continue;
56046     }
56047
56048     // autolink
56049     if (cap = this.rules.autolink.exec(src)) {
56050       src = src.substring(cap[0].length);
56051       if (cap[2] === '@') {
56052         text = cap[1].charAt(6) === ':'
56053           ? this.mangle(cap[1].substring(7))
56054           : this.mangle(cap[1]);
56055         href = this.mangle('mailto:') + text;
56056       } else {
56057         text = escape(cap[1]);
56058         href = text;
56059       }
56060       out += this.renderer.link(href, null, text);
56061       continue;
56062     }
56063
56064     // url (gfm)
56065     if (!this.inLink && (cap = this.rules.url.exec(src))) {
56066       src = src.substring(cap[0].length);
56067       text = escape(cap[1]);
56068       href = text;
56069       out += this.renderer.link(href, null, text);
56070       continue;
56071     }
56072
56073     // tag
56074     if (cap = this.rules.tag.exec(src)) {
56075       if (!this.inLink && /^<a /i.test(cap[0])) {
56076         this.inLink = true;
56077       } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
56078         this.inLink = false;
56079       }
56080       src = src.substring(cap[0].length);
56081       out += this.options.sanitize
56082         ? this.options.sanitizer
56083           ? this.options.sanitizer(cap[0])
56084           : escape(cap[0])
56085         : cap[0];
56086       continue;
56087     }
56088
56089     // link
56090     if (cap = this.rules.link.exec(src)) {
56091       src = src.substring(cap[0].length);
56092       this.inLink = true;
56093       out += this.outputLink(cap, {
56094         href: cap[2],
56095         title: cap[3]
56096       });
56097       this.inLink = false;
56098       continue;
56099     }
56100
56101     // reflink, nolink
56102     if ((cap = this.rules.reflink.exec(src))
56103         || (cap = this.rules.nolink.exec(src))) {
56104       src = src.substring(cap[0].length);
56105       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
56106       link = this.links[link.toLowerCase()];
56107       if (!link || !link.href) {
56108         out += cap[0].charAt(0);
56109         src = cap[0].substring(1) + src;
56110         continue;
56111       }
56112       this.inLink = true;
56113       out += this.outputLink(cap, link);
56114       this.inLink = false;
56115       continue;
56116     }
56117
56118     // strong
56119     if (cap = this.rules.strong.exec(src)) {
56120       src = src.substring(cap[0].length);
56121       out += this.renderer.strong(this.output(cap[2] || cap[1]));
56122       continue;
56123     }
56124
56125     // em
56126     if (cap = this.rules.em.exec(src)) {
56127       src = src.substring(cap[0].length);
56128       out += this.renderer.em(this.output(cap[2] || cap[1]));
56129       continue;
56130     }
56131
56132     // code
56133     if (cap = this.rules.code.exec(src)) {
56134       src = src.substring(cap[0].length);
56135       out += this.renderer.codespan(escape(cap[2], true));
56136       continue;
56137     }
56138
56139     // br
56140     if (cap = this.rules.br.exec(src)) {
56141       src = src.substring(cap[0].length);
56142       out += this.renderer.br();
56143       continue;
56144     }
56145
56146     // del (gfm)
56147     if (cap = this.rules.del.exec(src)) {
56148       src = src.substring(cap[0].length);
56149       out += this.renderer.del(this.output(cap[1]));
56150       continue;
56151     }
56152
56153     // text
56154     if (cap = this.rules.text.exec(src)) {
56155       src = src.substring(cap[0].length);
56156       out += this.renderer.text(escape(this.smartypants(cap[0])));
56157       continue;
56158     }
56159
56160     if (src) {
56161       throw new
56162         Error('Infinite loop on byte: ' + src.charCodeAt(0));
56163     }
56164   }
56165
56166   return out;
56167 };
56168
56169 /**
56170  * Compile Link
56171  */
56172
56173 InlineLexer.prototype.outputLink = function(cap, link) {
56174   var href = escape(link.href)
56175     , title = link.title ? escape(link.title) : null;
56176
56177   return cap[0].charAt(0) !== '!'
56178     ? this.renderer.link(href, title, this.output(cap[1]))
56179     : this.renderer.image(href, title, escape(cap[1]));
56180 };
56181
56182 /**
56183  * Smartypants Transformations
56184  */
56185
56186 InlineLexer.prototype.smartypants = function(text) {
56187   if (!this.options.smartypants) return text;
56188   return text
56189     // em-dashes
56190     .replace(/---/g, '\u2014')
56191     // en-dashes
56192     .replace(/--/g, '\u2013')
56193     // opening singles
56194     .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
56195     // closing singles & apostrophes
56196     .replace(/'/g, '\u2019')
56197     // opening doubles
56198     .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
56199     // closing doubles
56200     .replace(/"/g, '\u201d')
56201     // ellipses
56202     .replace(/\.{3}/g, '\u2026');
56203 };
56204
56205 /**
56206  * Mangle Links
56207  */
56208
56209 InlineLexer.prototype.mangle = function(text) {
56210   if (!this.options.mangle) return text;
56211   var out = ''
56212     , l = text.length
56213     , i = 0
56214     , ch;
56215
56216   for (; i < l; i++) {
56217     ch = text.charCodeAt(i);
56218     if (Math.random() > 0.5) {
56219       ch = 'x' + ch.toString(16);
56220     }
56221     out += '&#' + ch + ';';
56222   }
56223
56224   return out;
56225 };
56226
56227 /**
56228  * Renderer
56229  */
56230
56231 function Renderer(options) {
56232   this.options = options || {};
56233 }
56234
56235 Renderer.prototype.code = function(code, lang, escaped) {
56236   if (this.options.highlight) {
56237     var out = this.options.highlight(code, lang);
56238     if (out != null && out !== code) {
56239       escaped = true;
56240       code = out;
56241     }
56242   }
56243
56244   if (!lang) {
56245     return '<pre><code>'
56246       + (escaped ? code : escape(code, true))
56247       + '\n</code></pre>';
56248   }
56249
56250   return '<pre><code class="'
56251     + this.options.langPrefix
56252     + escape(lang, true)
56253     + '">'
56254     + (escaped ? code : escape(code, true))
56255     + '\n</code></pre>\n';
56256 };
56257
56258 Renderer.prototype.blockquote = function(quote) {
56259   return '<blockquote>\n' + quote + '</blockquote>\n';
56260 };
56261
56262 Renderer.prototype.html = function(html) {
56263   return html;
56264 };
56265
56266 Renderer.prototype.heading = function(text, level, raw) {
56267   return '<h'
56268     + level
56269     + ' id="'
56270     + this.options.headerPrefix
56271     + raw.toLowerCase().replace(/[^\w]+/g, '-')
56272     + '">'
56273     + text
56274     + '</h'
56275     + level
56276     + '>\n';
56277 };
56278
56279 Renderer.prototype.hr = function() {
56280   return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
56281 };
56282
56283 Renderer.prototype.list = function(body, ordered) {
56284   var type = ordered ? 'ol' : 'ul';
56285   return '<' + type + '>\n' + body + '</' + type + '>\n';
56286 };
56287
56288 Renderer.prototype.listitem = function(text) {
56289   return '<li>' + text + '</li>\n';
56290 };
56291
56292 Renderer.prototype.paragraph = function(text) {
56293   return '<p>' + text + '</p>\n';
56294 };
56295
56296 Renderer.prototype.table = function(header, body) {
56297   return '<table>\n'
56298     + '<thead>\n'
56299     + header
56300     + '</thead>\n'
56301     + '<tbody>\n'
56302     + body
56303     + '</tbody>\n'
56304     + '</table>\n';
56305 };
56306
56307 Renderer.prototype.tablerow = function(content) {
56308   return '<tr>\n' + content + '</tr>\n';
56309 };
56310
56311 Renderer.prototype.tablecell = function(content, flags) {
56312   var type = flags.header ? 'th' : 'td';
56313   var tag = flags.align
56314     ? '<' + type + ' style="text-align:' + flags.align + '">'
56315     : '<' + type + '>';
56316   return tag + content + '</' + type + '>\n';
56317 };
56318
56319 // span level renderer
56320 Renderer.prototype.strong = function(text) {
56321   return '<strong>' + text + '</strong>';
56322 };
56323
56324 Renderer.prototype.em = function(text) {
56325   return '<em>' + text + '</em>';
56326 };
56327
56328 Renderer.prototype.codespan = function(text) {
56329   return '<code>' + text + '</code>';
56330 };
56331
56332 Renderer.prototype.br = function() {
56333   return this.options.xhtml ? '<br/>' : '<br>';
56334 };
56335
56336 Renderer.prototype.del = function(text) {
56337   return '<del>' + text + '</del>';
56338 };
56339
56340 Renderer.prototype.link = function(href, title, text) {
56341   if (this.options.sanitize) {
56342     try {
56343       var prot = decodeURIComponent(unescape(href))
56344         .replace(/[^\w:]/g, '')
56345         .toLowerCase();
56346     } catch (e) {
56347       return '';
56348     }
56349     if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
56350       return '';
56351     }
56352   }
56353   var out = '<a href="' + href + '"';
56354   if (title) {
56355     out += ' title="' + title + '"';
56356   }
56357   out += '>' + text + '</a>';
56358   return out;
56359 };
56360
56361 Renderer.prototype.image = function(href, title, text) {
56362   var out = '<img src="' + href + '" alt="' + text + '"';
56363   if (title) {
56364     out += ' title="' + title + '"';
56365   }
56366   out += this.options.xhtml ? '/>' : '>';
56367   return out;
56368 };
56369
56370 Renderer.prototype.text = function(text) {
56371   return text;
56372 };
56373
56374 /**
56375  * Parsing & Compiling
56376  */
56377
56378 function Parser(options) {
56379   this.tokens = [];
56380   this.token = null;
56381   this.options = options || marked.defaults;
56382   this.options.renderer = this.options.renderer || new Renderer;
56383   this.renderer = this.options.renderer;
56384   this.renderer.options = this.options;
56385 }
56386
56387 /**
56388  * Static Parse Method
56389  */
56390
56391 Parser.parse = function(src, options, renderer) {
56392   var parser = new Parser(options, renderer);
56393   return parser.parse(src);
56394 };
56395
56396 /**
56397  * Parse Loop
56398  */
56399
56400 Parser.prototype.parse = function(src) {
56401   this.inline = new InlineLexer(src.links, this.options, this.renderer);
56402   this.tokens = src.reverse();
56403
56404   var out = '';
56405   while (this.next()) {
56406     out += this.tok();
56407   }
56408
56409   return out;
56410 };
56411
56412 /**
56413  * Next Token
56414  */
56415
56416 Parser.prototype.next = function() {
56417   return this.token = this.tokens.pop();
56418 };
56419
56420 /**
56421  * Preview Next Token
56422  */
56423
56424 Parser.prototype.peek = function() {
56425   return this.tokens[this.tokens.length - 1] || 0;
56426 };
56427
56428 /**
56429  * Parse Text Tokens
56430  */
56431
56432 Parser.prototype.parseText = function() {
56433   var body = this.token.text;
56434
56435   while (this.peek().type === 'text') {
56436     body += '\n' + this.next().text;
56437   }
56438
56439   return this.inline.output(body);
56440 };
56441
56442 /**
56443  * Parse Current Token
56444  */
56445
56446 Parser.prototype.tok = function() {
56447   switch (this.token.type) {
56448     case 'space': {
56449       return '';
56450     }
56451     case 'hr': {
56452       return this.renderer.hr();
56453     }
56454     case 'heading': {
56455       return this.renderer.heading(
56456         this.inline.output(this.token.text),
56457         this.token.depth,
56458         this.token.text);
56459     }
56460     case 'code': {
56461       return this.renderer.code(this.token.text,
56462         this.token.lang,
56463         this.token.escaped);
56464     }
56465     case 'table': {
56466       var header = ''
56467         , body = ''
56468         , i
56469         , row
56470         , cell
56471         , flags
56472         , j;
56473
56474       // header
56475       cell = '';
56476       for (i = 0; i < this.token.header.length; i++) {
56477         flags = { header: true, align: this.token.align[i] };
56478         cell += this.renderer.tablecell(
56479           this.inline.output(this.token.header[i]),
56480           { header: true, align: this.token.align[i] }
56481         );
56482       }
56483       header += this.renderer.tablerow(cell);
56484
56485       for (i = 0; i < this.token.cells.length; i++) {
56486         row = this.token.cells[i];
56487
56488         cell = '';
56489         for (j = 0; j < row.length; j++) {
56490           cell += this.renderer.tablecell(
56491             this.inline.output(row[j]),
56492             { header: false, align: this.token.align[j] }
56493           );
56494         }
56495
56496         body += this.renderer.tablerow(cell);
56497       }
56498       return this.renderer.table(header, body);
56499     }
56500     case 'blockquote_start': {
56501       var body = '';
56502
56503       while (this.next().type !== 'blockquote_end') {
56504         body += this.tok();
56505       }
56506
56507       return this.renderer.blockquote(body);
56508     }
56509     case 'list_start': {
56510       var body = ''
56511         , ordered = this.token.ordered;
56512
56513       while (this.next().type !== 'list_end') {
56514         body += this.tok();
56515       }
56516
56517       return this.renderer.list(body, ordered);
56518     }
56519     case 'list_item_start': {
56520       var body = '';
56521
56522       while (this.next().type !== 'list_item_end') {
56523         body += this.token.type === 'text'
56524           ? this.parseText()
56525           : this.tok();
56526       }
56527
56528       return this.renderer.listitem(body);
56529     }
56530     case 'loose_item_start': {
56531       var body = '';
56532
56533       while (this.next().type !== 'list_item_end') {
56534         body += this.tok();
56535       }
56536
56537       return this.renderer.listitem(body);
56538     }
56539     case 'html': {
56540       var html = !this.token.pre && !this.options.pedantic
56541         ? this.inline.output(this.token.text)
56542         : this.token.text;
56543       return this.renderer.html(html);
56544     }
56545     case 'paragraph': {
56546       return this.renderer.paragraph(this.inline.output(this.token.text));
56547     }
56548     case 'text': {
56549       return this.renderer.paragraph(this.parseText());
56550     }
56551   }
56552 };
56553
56554 /**
56555  * Helpers
56556  */
56557
56558 function escape(html, encode) {
56559   return html
56560     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
56561     .replace(/</g, '&lt;')
56562     .replace(/>/g, '&gt;')
56563     .replace(/"/g, '&quot;')
56564     .replace(/'/g, '&#39;');
56565 }
56566
56567 function unescape(html) {
56568         // explicitly match decimal, hex, and named HTML entities 
56569   return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
56570     n = n.toLowerCase();
56571     if (n === 'colon') return ':';
56572     if (n.charAt(0) === '#') {
56573       return n.charAt(1) === 'x'
56574         ? String.fromCharCode(parseInt(n.substring(2), 16))
56575         : String.fromCharCode(+n.substring(1));
56576     }
56577     return '';
56578   });
56579 }
56580
56581 function replace(regex, opt) {
56582   regex = regex.source;
56583   opt = opt || '';
56584   return function self(name, val) {
56585     if (!name) return new RegExp(regex, opt);
56586     val = val.source || val;
56587     val = val.replace(/(^|[^\[])\^/g, '$1');
56588     regex = regex.replace(name, val);
56589     return self;
56590   };
56591 }
56592
56593 function noop() {}
56594 noop.exec = noop;
56595
56596 function merge(obj) {
56597   var i = 1
56598     , target
56599     , key;
56600
56601   for (; i < arguments.length; i++) {
56602     target = arguments[i];
56603     for (key in target) {
56604       if (Object.prototype.hasOwnProperty.call(target, key)) {
56605         obj[key] = target[key];
56606       }
56607     }
56608   }
56609
56610   return obj;
56611 }
56612
56613
56614 /**
56615  * Marked
56616  */
56617
56618 function marked(src, opt, callback) {
56619   if (callback || typeof opt === 'function') {
56620     if (!callback) {
56621       callback = opt;
56622       opt = null;
56623     }
56624
56625     opt = merge({}, marked.defaults, opt || {});
56626
56627     var highlight = opt.highlight
56628       , tokens
56629       , pending
56630       , i = 0;
56631
56632     try {
56633       tokens = Lexer.lex(src, opt);
56634     } catch (e) {
56635       return callback(e);
56636     }
56637
56638     pending = tokens.length;
56639
56640     var done = function(err) {
56641       if (err) {
56642         opt.highlight = highlight;
56643         return callback(err);
56644       }
56645
56646       var out;
56647
56648       try {
56649         out = Parser.parse(tokens, opt);
56650       } catch (e) {
56651         err = e;
56652       }
56653
56654       opt.highlight = highlight;
56655
56656       return err
56657         ? callback(err)
56658         : callback(null, out);
56659     };
56660
56661     if (!highlight || highlight.length < 3) {
56662       return done();
56663     }
56664
56665     delete opt.highlight;
56666
56667     if (!pending) return done();
56668
56669     for (; i < tokens.length; i++) {
56670       (function(token) {
56671         if (token.type !== 'code') {
56672           return --pending || done();
56673         }
56674         return highlight(token.text, token.lang, function(err, code) {
56675           if (err) return done(err);
56676           if (code == null || code === token.text) {
56677             return --pending || done();
56678           }
56679           token.text = code;
56680           token.escaped = true;
56681           --pending || done();
56682         });
56683       })(tokens[i]);
56684     }
56685
56686     return;
56687   }
56688   try {
56689     if (opt) opt = merge({}, marked.defaults, opt);
56690     return Parser.parse(Lexer.lex(src, opt), opt);
56691   } catch (e) {
56692     e.message += '\nPlease report this to https://github.com/chjj/marked.';
56693     if ((opt || marked.defaults).silent) {
56694       return '<p>An error occured:</p><pre>'
56695         + escape(e.message + '', true)
56696         + '</pre>';
56697     }
56698     throw e;
56699   }
56700 }
56701
56702 /**
56703  * Options
56704  */
56705
56706 marked.options =
56707 marked.setOptions = function(opt) {
56708   merge(marked.defaults, opt);
56709   return marked;
56710 };
56711
56712 marked.defaults = {
56713   gfm: true,
56714   tables: true,
56715   breaks: false,
56716   pedantic: false,
56717   sanitize: false,
56718   sanitizer: null,
56719   mangle: true,
56720   smartLists: false,
56721   silent: false,
56722   highlight: null,
56723   langPrefix: 'lang-',
56724   smartypants: false,
56725   headerPrefix: '',
56726   renderer: new Renderer,
56727   xhtml: false
56728 };
56729
56730 /**
56731  * Expose
56732  */
56733
56734 marked.Parser = Parser;
56735 marked.parser = Parser.parse;
56736
56737 marked.Renderer = Renderer;
56738
56739 marked.Lexer = Lexer;
56740 marked.lexer = Lexer.lex;
56741
56742 marked.InlineLexer = InlineLexer;
56743 marked.inlineLexer = InlineLexer.output;
56744
56745 marked.parse = marked;
56746
56747 if (typeof module !== 'undefined' && typeof exports === 'object') {
56748   module.exports = marked;
56749 } else if (typeof define === 'function' && define.amd) {
56750   define(function() { return marked; });
56751 } else {
56752   this.marked = marked;
56753 }
56754
56755 }).call(function() {
56756   return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
56757 }());
56758 });
56759
56760 // toggles the visibility of ui elements, using a combination of the
56761 // hide class, which sets display=none, and a d3 transition for opacity.
56762 // this will cause blinking when called repeatedly, so check that the
56763 // value actually changes between calls.
56764 function uiToggle(show, callback) {
56765     return function(selection$$1) {
56766         selection$$1
56767             .style('opacity', show ? 0 : 1)
56768             .classed('hide', false)
56769             .transition()
56770             .style('opacity', show ? 1 : 0)
56771             .on('end', function() {
56772                 select(this)
56773                     .classed('hide', !show)
56774                     .style('opacity', null);
56775                 if (callback) callback.apply(this);
56776             });
56777     };
56778 }
56779
56780 // Tooltips and svg mask used to highlight certain features
56781 function d3curtain() {
56782
56783     var dispatch$$1 = dispatch(),
56784         surface = select(null),
56785         tooltip = select(null),
56786         darkness = select(null);
56787
56788     function curtain(selection$$1) {
56789         surface = selection$$1
56790             .append('svg')
56791             .attr('id', 'curtain')
56792             .style('z-index', 1000)
56793             .style('pointer-events', 'none')
56794             .style('position', 'absolute')
56795             .style('top', 0)
56796             .style('left', 0);
56797
56798         darkness = surface.append('path')
56799             .attr('x', 0)
56800             .attr('y', 0)
56801             .attr('class', 'curtain-darkness');
56802
56803         select(window).on('resize.curtain', resize);
56804
56805         tooltip = selection$$1.append('div')
56806             .attr('class', 'tooltip')
56807             .style('z-index', 1002);
56808
56809         tooltip
56810             .append('div')
56811             .attr('class', 'tooltip-arrow');
56812
56813         tooltip
56814             .append('div')
56815             .attr('class', 'tooltip-inner');
56816
56817         resize();
56818
56819
56820         function resize() {
56821             surface
56822                 .attr('width', window.innerWidth)
56823                 .attr('height', window.innerHeight);
56824             curtain.cut(darkness.datum());
56825         }
56826     }
56827
56828
56829     curtain.reveal = function(box, text$$1, tooltipclass, duration) {
56830         if (typeof box === 'string') box = select(box).node();
56831         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
56832
56833         curtain.cut(box, duration);
56834
56835         if (text$$1) {
56836             // pseudo markdown bold text hack
56837             var parts = text$$1.split('**');
56838             var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
56839             if (parts[1]) html$$1 += '<span class="bold">' + parts[1] + '</span>';
56840
56841             var selection$$1 = tooltip
56842                 .classed('in', true)
56843                 .selectAll('.tooltip-inner')
56844                 .html(html$$1);
56845
56846             var dimensions = utilGetDimensions(selection$$1, true),
56847                 w = window.innerWidth,
56848                 h = window.innerHeight,
56849                 side, pos;
56850
56851             // trim box dimensions to just the portion that fits in the window..
56852             if (box.top + box.height > h) {
56853                 box.height -= (box.top + box.height - h);
56854             }
56855             if (box.left + box.width > w) {
56856                 box.width -= (box.left + box.width - w);
56857             }
56858
56859             // determine tooltip placement..
56860             if (box.top + box.height < Math.min(100, box.width + box.left)) {
56861                 side = 'bottom';
56862                 pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top + box.height];
56863
56864             } else if (box.left + box.width + 300 < w) {
56865                 side = 'right';
56866                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
56867
56868             } else if (box.left > 300) {
56869                 side = 'left';
56870                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
56871
56872             } else {
56873                 side = 'bottom';
56874                 pos = [box.left, box.top + box.height];
56875             }
56876
56877             pos = [
56878                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
56879                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
56880             ];
56881
56882             if (duration !== 0 || !tooltip.classed(side)) {
56883                 tooltip.call(uiToggle(true));
56884             }
56885
56886             tooltip
56887                 .style('top', pos[1] + 'px')
56888                 .style('left', pos[0] + 'px')
56889                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass);
56890
56891         } else {
56892             tooltip.call(uiToggle(false));
56893         }
56894     };
56895
56896
56897     curtain.cut = function(datum, duration) {
56898         darkness.datum(datum)
56899             .interrupt();
56900
56901         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
56902             .attr('d', function(d) {
56903                 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
56904                     window.innerWidth + ',' + window.innerHeight + 'L' +
56905                     window.innerWidth + ',0 Z';
56906
56907                 if (!d) return string;
56908                 return string + 'M' +
56909                     d.left + ',' + d.top + 'L' +
56910                     d.left + ',' + (d.top + d.height) + 'L' +
56911                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
56912                     (d.left + d.width) + ',' + (d.top) + 'Z';
56913
56914             });
56915     };
56916
56917
56918     curtain.remove = function() {
56919         surface.remove();
56920         tooltip.remove();
56921     };
56922
56923
56924     return utilRebind(curtain, dispatch$$1, 'on');
56925 }
56926
56927 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"]}};
56928
56929 function pointBox(point, context) {
56930     var rect = context.surfaceRect();
56931     point = context.projection(point);
56932     return {
56933         left: point[0] + rect.left - 30,
56934         top: point[1] + rect.top - 50,
56935         width: 60,
56936         height: 70
56937      };
56938 }
56939
56940
56941 function pad$1(box, padding, context) {
56942     if (box instanceof Array) {
56943         var rect = context.surfaceRect();
56944         box = context.projection(box);
56945         box = {
56946             left: box[0] + rect.left,
56947             top: box[1] + rect.top
56948         };
56949     }
56950     return {
56951         left: box.left - padding,
56952         top: box.top - padding,
56953         width: (box.width || 0) + 2 * padding,
56954         height: (box.width || 0) + 2 * padding
56955     };
56956 }
56957
56958
56959 function icon(name, svgklass) {
56960     return '<svg class="icon ' + (svgklass || '') + '">' +
56961          '<use xlink:href="' + name + '"></use></svg>';
56962  }
56963
56964 function uiIntroNavigation(context, reveal) {
56965     var dispatch$$1 = dispatch('done'),
56966         timeouts = [];
56967
56968     var step = {
56969         title: 'intro.navigation.title'
56970     };
56971
56972
56973     function set$$1(f, t$$1) {
56974         timeouts.push(window.setTimeout(f, t$$1));
56975     }
56976
56977
56978     function eventCancel() {
56979         event.stopPropagation();
56980         event.preventDefault();
56981     }
56982
56983
56984     step.enter = function() {
56985         var rect = context.surfaceRect(),
56986             map$$1 = {
56987                 left: rect.left + 10,
56988                 top: rect.top + 70,
56989                 width: rect.width - 70,
56990                 height: rect.height - 170
56991             };
56992
56993         context.map().centerZoom([-85.63591, 41.94285], 19);
56994
56995         reveal(map$$1, t('intro.navigation.drag'));
56996
56997         context.map().on('move.intro', lodash.debounce(function() {
56998             context.map().on('move.intro', null);
56999             townhall();
57000             context.on('enter.intro', inspectTownHall);
57001         }, 400));
57002
57003
57004         function townhall() {
57005             var hall = [-85.63645945147184, 41.942986488012565];
57006             var point = context.projection(hall);
57007
57008             if (point[0] < 0 || point[0] > rect.width ||
57009                 point[1] < 0 || point[1] > rect.height) {
57010                 context.map().center(hall);
57011             }
57012
57013             var box = pointBox(hall, context);
57014             reveal(box, t('intro.navigation.select'));
57015
57016             context.map().on('move.intro', function() {
57017                 var box = pointBox(hall, context);
57018                 reveal(box, t('intro.navigation.select'), {duration: 0});
57019             });
57020         }
57021
57022
57023         function inspectTownHall(mode) {
57024             if (mode.id !== 'select') return;
57025             context.on('enter.intro', null);
57026             context.map().on('move.intro', null);
57027             set$$1(function() {
57028                 reveal('.entity-editor-pane',
57029                     t('intro.navigation.pane', { button: icon('#icon-close', 'pre-text') }));
57030                 context.on('exit.intro', streetSearch);
57031             }, 700);
57032         }
57033
57034
57035         function streetSearch() {
57036             context.on('exit.intro', null);
57037             reveal('.search-header input',
57038                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
57039             select('.search-header input')
57040                 .on('keyup.intro', searchResult);
57041         }
57042
57043
57044         function searchResult() {
57045             var first = select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
57046                 firstName = first.select('.entity-name'),
57047                 name = t('intro.graph.spring_st');
57048
57049             if (!firstName.empty() && firstName.text() === name) {
57050                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
57051                 context.on('exit.intro', selectedStreet);
57052                 select('.search-header input')
57053                     .on('keydown.intro', eventCancel, true)
57054                     .on('keyup.intro', null);
57055             }
57056         }
57057
57058
57059         function selectedStreet() {
57060             var springSt = [-85.63585099140167, 41.942506848938926];
57061             context.map().center(springSt);
57062             context.on('exit.intro', function() {
57063                 dispatch$$1.call('done');
57064             });
57065
57066             set$$1(function() {
57067                 reveal('.entity-editor-pane',
57068                     t('intro.navigation.chosen', {
57069                         name: t('intro.graph.spring_st'),
57070                         button: icon('#icon-close', 'pre-text')
57071                     }));
57072             }, 400);
57073         }
57074     };
57075
57076
57077     step.exit = function() {
57078         timeouts.forEach(window.clearTimeout);
57079         context.map().on('move.intro', null);
57080         context.on('enter.intro', null);
57081         context.on('exit.intro', null);
57082         select('.search-header input')
57083             .on('keydown.intro', null)
57084             .on('keyup.intro', null);
57085     };
57086
57087
57088     return utilRebind(step, dispatch$$1, 'on');
57089 }
57090
57091 function uiIntroPoint(context, reveal) {
57092     var dispatch$$1 = dispatch('done'),
57093         timeouts = [];
57094
57095     var step = {
57096         title: 'intro.points.title'
57097     };
57098
57099
57100     function setTimeout(f, t$$1) {
57101         timeouts.push(window.setTimeout(f, t$$1));
57102     }
57103
57104
57105     function eventCancel() {
57106         event.stopPropagation();
57107         event.preventDefault();
57108     }
57109
57110
57111     step.enter = function() {
57112         context.map().centerZoom([-85.63279, 41.94394], 19);
57113         reveal('button.add-point',
57114             t('intro.points.add', { button: icon('#icon-point', 'pre-text') }),
57115             { tooltipClass: 'intro-points-add' });
57116
57117         var corner = [-85.632481,41.944094];
57118
57119         context.on('enter.intro', addPoint);
57120
57121
57122         function addPoint(mode) {
57123             if (mode.id !== 'add-point') return;
57124             context.on('enter.intro', enterSelect);
57125
57126             var pointBox$$1 = pad$1(corner, 150, context);
57127             reveal(pointBox$$1, t('intro.points.place'));
57128
57129             context.map().on('move.intro', function() {
57130                 pointBox$$1 = pad$1(corner, 150, context);
57131                 reveal(pointBox$$1, t('intro.points.place'), {duration: 0});
57132             });
57133         }
57134
57135
57136         function enterSelect(mode) {
57137             if (mode.id !== 'select') return;
57138             context.map().on('move.intro', null);
57139             context.on('enter.intro', null);
57140
57141             setTimeout(function() {
57142                 reveal('.preset-search-input',
57143                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
57144                 select('.preset-search-input').on('keyup.intro', keySearch);
57145             }, 500);
57146         }
57147
57148
57149         function keySearch() {
57150             var first = select('.preset-list-item:first-child');
57151             if (first.classed('preset-amenity-cafe')) {
57152                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
57153                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
57154                 select('.preset-search-input')
57155                     .on('keydown.intro', eventCancel, true)
57156                     .on('keyup.intro', null);
57157             }
57158         }
57159
57160
57161         function selectedPreset() {
57162             setTimeout(function() {
57163                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
57164                 context.history().on('change.intro', closeEditor);
57165                 context.on('exit.intro', selectPoint);
57166             }, 400);
57167         }
57168
57169
57170         function closeEditor() {
57171             select('.preset-search-input').on('keydown.intro', null);
57172             context.history().on('change.intro', null);
57173             reveal('.entity-editor-pane',
57174                 t('intro.points.close', { button: icon('#icon-apply', 'pre-text') }));
57175         }
57176
57177
57178         function selectPoint() {
57179             context.on('exit.intro', null);
57180             context.history().on('change.intro', null);
57181             context.on('enter.intro', enterReselect);
57182
57183             var pointBox$$1 = pad$1(corner, 150, context);
57184             reveal(pointBox$$1, t('intro.points.reselect'));
57185
57186             context.map().on('move.intro', function() {
57187                 pointBox$$1 = pad$1(corner, 150, context);
57188                 reveal(pointBox$$1, t('intro.points.reselect'), {duration: 0});
57189             });
57190         }
57191
57192
57193         function enterReselect(mode) {
57194             if (mode.id !== 'select') return;
57195             context.map().on('move.intro', null);
57196             context.on('enter.intro', null);
57197
57198             setTimeout(function() {
57199                 reveal('.entity-editor-pane',
57200                     t('intro.points.fixname', { button: icon('#icon-apply', 'pre-text') }));
57201                 context.on('exit.intro', deletePoint);
57202             }, 500);
57203         }
57204
57205
57206         function deletePoint() {
57207             context.on('exit.intro', null);
57208             context.on('enter.intro', enterDelete);
57209
57210             var pointBox$$1 = pad$1(corner, 150, context);
57211             reveal(pointBox$$1, t('intro.points.reselect_delete'));
57212
57213             context.map().on('move.intro', function() {
57214                 pointBox$$1 = pad$1(corner, 150, context);
57215                 reveal(pointBox$$1, t('intro.points.reselect_delete'), {duration: 0});
57216             });
57217         }
57218
57219
57220         function enterDelete(mode) {
57221             if (mode.id !== 'select') return;
57222             context.map().on('move.intro', null);
57223             context.on('enter.intro', null);
57224             context.on('exit.intro', deletePoint);
57225             context.map().on('move.intro', deletePoint);
57226             context.history().on('change.intro', deleted);
57227
57228             setTimeout(function() {
57229                 var node = select('.radial-menu-item-delete').node();
57230                 var pointBox$$1 = pad$1(node.getBoundingClientRect(), 50, context);
57231                 reveal(pointBox$$1,
57232                     t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
57233             }, 300);
57234         }
57235
57236
57237         function deleted(changed) {
57238             if (changed.deleted().length) {
57239                 dispatch$$1.call('done');
57240             }
57241         }
57242
57243     };
57244
57245
57246     step.exit = function() {
57247         timeouts.forEach(window.clearTimeout);
57248         context.on('exit.intro', null);
57249         context.on('enter.intro', null);
57250         context.map().on('move.intro', null);
57251         context.history().on('change.intro', null);
57252         select('.preset-search-input')
57253             .on('keyup.intro', null)
57254             .on('keydown.intro', null);
57255     };
57256
57257     return utilRebind(step, dispatch$$1, 'on');
57258 }
57259
57260 function uiIntroArea(context, reveal) {
57261     var dispatch$$1 = dispatch('done'),
57262         timeout$$1;
57263
57264     var step = {
57265         title: 'intro.areas.title'
57266     };
57267
57268
57269     step.enter = function() {
57270         var playground = [-85.63552, 41.94159],
57271             corner = [-85.63565411045074, 41.9417715536927];
57272         context.map().centerZoom(playground, 19);
57273         reveal('button.add-area',
57274             t('intro.areas.add', { button: icon('#icon-area', 'pre-text') }),
57275             { tooltipClass: 'intro-areas-add' });
57276
57277         context.on('enter.intro', addArea);
57278
57279
57280         function addArea(mode) {
57281             if (mode.id !== 'add-area') return;
57282             context.on('enter.intro', drawArea);
57283
57284             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
57285             var pointBox$$1 = pad$1(corner, padding, context);
57286             reveal(pointBox$$1, t('intro.areas.corner'));
57287
57288             context.map().on('move.intro', function() {
57289                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
57290                 pointBox$$1 = pad$1(corner, padding, context);
57291                 reveal(pointBox$$1, t('intro.areas.corner'), {duration: 0});
57292             });
57293         }
57294
57295
57296         function drawArea(mode) {
57297             if (mode.id !== 'draw-area') return;
57298             context.on('enter.intro', enterSelect);
57299
57300             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
57301             var pointBox$$1 = pad$1(playground, padding, context);
57302             reveal(pointBox$$1, t('intro.areas.place'));
57303
57304             context.map().on('move.intro', function() {
57305                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
57306                 pointBox$$1 = pad$1(playground, padding, context);
57307                 reveal(pointBox$$1, t('intro.areas.place'), {duration: 0});
57308             });
57309         }
57310
57311
57312         function enterSelect(mode) {
57313             if (mode.id !== 'select') return;
57314             context.map().on('move.intro', null);
57315             context.on('enter.intro', null);
57316
57317             timeout$$1 = setTimeout(function() {
57318                 reveal('.preset-search-input',
57319                     t('intro.areas.search',
57320                     { name: context.presets().item('leisure/playground').name() }));
57321                 select('.preset-search-input').on('keyup.intro', keySearch);
57322             }, 500);
57323         }
57324
57325
57326         function keySearch() {
57327             var first = select('.preset-list-item:first-child');
57328             if (first.classed('preset-leisure-playground')) {
57329                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
57330                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
57331                 select('.preset-search-input').on('keyup.intro', null);
57332             }
57333         }
57334
57335
57336         function selectedPreset() {
57337             reveal('.pane',
57338                 t('intro.areas.describe', { button: icon('#icon-apply', 'pre-text') }));
57339             context.on('exit.intro', function() {
57340                 dispatch$$1.call('done');
57341             });
57342         }
57343     };
57344
57345
57346     step.exit = function() {
57347         window.clearTimeout(timeout$$1);
57348         context.on('enter.intro', null);
57349         context.on('exit.intro', null);
57350         context.history().on('change.intro', null);
57351         context.map().on('move.intro', null);
57352         select('.preset-search-input').on('keyup.intro', null);
57353     };
57354
57355
57356     return utilRebind(step, dispatch$$1, 'on');
57357 }
57358
57359 function uiIntroLine(context, reveal) {
57360     var dispatch$$1 = dispatch('done'),
57361         timeouts = [];
57362
57363     var step = {
57364         title: 'intro.lines.title'
57365     };
57366
57367
57368     function timeout$$1(f, t$$1) {
57369         timeouts.push(window.setTimeout(f, t$$1));
57370     }
57371
57372
57373     function eventCancel() {
57374         event.stopPropagation();
57375         event.preventDefault();
57376     }
57377
57378
57379     step.enter = function() {
57380         var centroid = [-85.62830, 41.95699];
57381         var midpoint = [-85.62975395449628, 41.95787501510204];
57382         var start = [-85.6297754121684, 41.95805253325314];
57383         var intersection = [-85.62974496187628, 41.95742515554585];
57384
57385         context.map().centerZoom(start, 18);
57386         reveal('button.add-line',
57387             t('intro.lines.add', { button: icon('#icon-line', 'pre-text') }),
57388             { tooltipClass: 'intro-lines-add' });
57389
57390         context.on('enter.intro', addLine);
57391
57392
57393         function addLine(mode) {
57394             if (mode.id !== 'add-line') return;
57395             context.on('enter.intro', drawLine);
57396
57397             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
57398             var pointBox$$1 = pad$1(start, padding, context);
57399             reveal(pointBox$$1, t('intro.lines.start'));
57400
57401             context.map().on('move.intro', function() {
57402                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
57403                 pointBox$$1 = pad$1(start, padding, context);
57404                 reveal(pointBox$$1, t('intro.lines.start'), {duration: 0});
57405             });
57406         }
57407
57408
57409         function drawLine(mode) {
57410             if (mode.id !== 'draw-line') return;
57411             context.history().on('change.intro', addIntersection);
57412             context.on('enter.intro', retry);
57413
57414             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
57415             var pointBox$$1 = pad$1(midpoint, padding, context);
57416             reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
57417
57418             context.map().on('move.intro', function() {
57419                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
57420                 pointBox$$1 = pad$1(midpoint, padding, context);
57421                 reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
57422             });
57423         }
57424
57425
57426         // ended line before creating intersection
57427         function retry(mode) {
57428             if (mode.id !== 'select') return;
57429             var pointBox$$1 = pad$1(intersection, 30, context),
57430                 ids = mode.selectedIDs();
57431             reveal(pointBox$$1, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
57432             select(window).on('mousedown.intro', eventCancel, true);
57433
57434             timeout$$1(function() {
57435                 context.replace(actionDeleteMultiple(ids));
57436                 step.exit();
57437                 step.enter();
57438             }, 3000);
57439         }
57440
57441
57442         function addIntersection(changes) {
57443             if ( lodash.some(changes.created(), function(d) {
57444                 return d.type === 'node' && context.graph().parentWays(d).length > 1;
57445             })) {
57446                 context.history().on('change.intro', null);
57447                 context.on('enter.intro', enterSelect);
57448
57449                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
57450                 var pointBox$$1 = pad$1(centroid, padding, context);
57451                 reveal(pointBox$$1, t('intro.lines.finish'));
57452
57453                 context.map().on('move.intro', function() {
57454                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
57455                     pointBox$$1 = pad$1(centroid, padding, context);
57456                     reveal(pointBox$$1, t('intro.lines.finish'), {duration: 0});
57457                 });
57458             }
57459         }
57460
57461
57462         function enterSelect(mode) {
57463             if (mode.id !== 'select') return;
57464             context.map().on('move.intro', null);
57465             context.on('enter.intro', null);
57466             select('#curtain').style('pointer-events', 'all');
57467
57468             presetCategory();
57469         }
57470
57471
57472         function presetCategory() {
57473             timeout$$1(function() {
57474                 select('#curtain').style('pointer-events', 'none');
57475                 var road = select('.preset-category-road .preset-list-button');
57476                 reveal(road.node(), t('intro.lines.road'));
57477                 utilBindOnce(road, 'click.intro', roadCategory);
57478             }, 500);
57479         }
57480
57481
57482         function roadCategory() {
57483             timeout$$1(function() {
57484                 var grid = select('.subgrid');
57485                 reveal(grid.node(), t('intro.lines.residential'));
57486                 utilBindOnce(grid.selectAll(':not(.preset-highway-residential) .preset-list-button'),
57487                     'click.intro', retryPreset);
57488                 utilBindOnce(grid.selectAll('.preset-highway-residential .preset-list-button'),
57489                     'click.intro', roadDetails);
57490             }, 500);
57491         }
57492
57493
57494         // selected wrong road type
57495         function retryPreset() {
57496             timeout$$1(function() {
57497                 var preset = select('.entity-editor-pane .preset-list-button');
57498                 reveal(preset.node(), t('intro.lines.wrong_preset'));
57499                 utilBindOnce(preset, 'click.intro', presetCategory);
57500             }, 500);
57501         }
57502
57503
57504         function roadDetails() {
57505             reveal('.pane',
57506                 t('intro.lines.describe', { button: icon('#icon-apply', 'pre-text') }));
57507             context.on('exit.intro', function() {
57508                 dispatch$$1.call('done');
57509             });
57510         }
57511     };
57512
57513
57514     step.exit = function() {
57515         select(window).on('mousedown.intro', null, true);
57516         select('#curtain').style('pointer-events', 'none');
57517         timeouts.forEach(window.clearTimeout);
57518         context.on('enter.intro', null);
57519         context.on('exit.intro', null);
57520         context.map().on('move.intro', null);
57521         context.history().on('change.intro', null);
57522     };
57523
57524     return utilRebind(step, dispatch$$1, 'on');
57525 }
57526
57527 function uiIntroStartEditing(context, reveal) {
57528     var dispatch$$1 = dispatch('done', 'startEditing'),
57529         modalSelection,
57530         timeouts = [];
57531
57532     var step = {
57533         title: 'intro.startediting.title'
57534     };
57535
57536
57537     function timeout$$1(f, t$$1) {
57538         timeouts.push(window.setTimeout(f, t$$1));
57539     }
57540
57541
57542     step.enter = function() {
57543         reveal('.map-control.help-control',
57544             t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }));
57545
57546         timeout$$1(function() {
57547             reveal('#bar button.save', t('intro.startediting.save'));
57548         }, 5000);
57549
57550         timeout$$1(function() {
57551             reveal('#surface');
57552         }, 10000);
57553
57554         timeout$$1(function() {
57555             modalSelection = uiModal(context.container());
57556
57557             modalSelection.select('.modal')
57558                 .attr('class', 'modal-splash modal col6');
57559
57560             modalSelection.selectAll('.close').remove();
57561
57562             var startbutton = modalSelection.select('.content')
57563                 .attr('class', 'fillL')
57564                 .append('button')
57565                     .attr('class', 'modal-section huge-modal-button')
57566                     .on('click', function() {
57567                         modalSelection.remove();
57568                     });
57569
57570                 startbutton
57571                     .append('div')
57572                     .attr('class','illustration');
57573
57574                 startbutton
57575                     .append('h2')
57576                     .text(t('intro.startediting.start'));
57577
57578             dispatch$$1.call('startEditing');
57579         }, 10500);
57580     };
57581
57582
57583     step.exit = function() {
57584         if (modalSelection) { modalSelection.remove(); }
57585         timeouts.forEach(window.clearTimeout);
57586     };
57587
57588
57589     return utilRebind(step, dispatch$$1, 'on');
57590 }
57591
57592 var sampleIntros = {
57593     navigation: uiIntroNavigation,
57594     point: uiIntroPoint,
57595     area: uiIntroArea,
57596     line: uiIntroLine,
57597     startEditing: uiIntroStartEditing
57598 };
57599
57600
57601 function uiIntro(context) {
57602     var step;
57603
57604     function localizedName(id) {
57605         var features = {
57606             n2140018997: 'city_hall',
57607             n367813436: 'fire_department',
57608             w203988286: 'memory_isle_park',
57609             w203972937: 'riverwalk_trail',
57610             w203972938: 'riverwalk_trail',
57611             w203972940: 'riverwalk_trail',
57612             w41785752: 'w_michigan_ave',
57613             w134150789: 'w_michigan_ave',
57614             w134150795: 'w_michigan_ave',
57615             w134150800: 'w_michigan_ave',
57616             w134150811: 'w_michigan_ave',
57617             w134150802: 'e_michigan_ave',
57618             w134150836: 'e_michigan_ave',
57619             w41074896: 'e_michigan_ave',
57620             w17965834: 'spring_st',
57621             w203986457: 'scidmore_park',
57622             w203049587: 'petting_zoo',
57623             w17967397: 'n_andrews_st',
57624             w17967315: 's_andrews_st',
57625             w17967326: 'n_constantine_st',
57626             w17966400: 's_constantine_st',
57627             w170848823: 'rocky_river',
57628             w170848824: 'rocky_river',
57629             w170848331: 'rocky_river',
57630             w17967752: 'railroad_dr',
57631             w17965998: 'conrail_rr',
57632             w134150845: 'conrail_rr',
57633             w170989131: 'st_joseph_river',
57634             w143497377: 'n_main_st',
57635             w134150801: 's_main_st',
57636             w134150830: 's_main_st',
57637             w17966462: 's_main_st',
57638             w17967734: 'water_st',
57639             w17964996: 'foster_st',
57640             w170848330: 'portage_river',
57641             w17965351: 'flower_st',
57642             w17965502: 'elm_st',
57643             w17965402: 'walnut_st',
57644             w17964793: 'morris_ave',
57645             w17967444: 'east_st',
57646             w17966984: 'portage_ave'
57647         };
57648
57649         return features[id] && t('intro.graph.' + features[id]);
57650     }
57651
57652
57653     var introGraph = {};
57654
57655     for (var key in dataIntroGraph) {
57656         introGraph[key] = osmEntity$$1(dataIntroGraph[key]);
57657         var name = localizedName(key);
57658         if (name) {
57659             introGraph[key].tags.name = name;
57660         }
57661     }
57662
57663
57664     function intro(selection$$1) {
57665         context.enter(modeBrowse$$1(context));
57666
57667         // Save current map state
57668         var history = context.history().toJSON(),
57669             hash = window.location.hash,
57670             center = context.map().center(),
57671             zoom$$1 = context.map().zoom(),
57672             background = context.background().baseLayerSource(),
57673             opacity = selectAll('#map .layer-background').style('opacity'),
57674             loadedTiles = context.connection().loadedTiles(),
57675             baseEntities = context.history().graph().base().entities;
57676
57677         // Block saving
57678         context.inIntro(true);
57679
57680         // Load semi-real data used in intro
57681         context.connection().toggle(false).reset();
57682         context.history().reset();
57683
57684         context.history().merge(values(coreGraph$$1().load(introGraph).entities));
57685         context.background().bing();
57686
57687         selectAll('#map .layer-background').style('opacity', 1);
57688
57689         var curtain = d3curtain();
57690         selection$$1.call(curtain);
57691
57692
57693         function reveal(box, text$$1, options) {
57694             options = options || {};
57695             curtain.reveal(box,
57696                 text$$1 || '',
57697                 options.tooltipClass || '',
57698                 options.duration
57699             );
57700         }
57701
57702         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
57703             var s = sampleIntros[step](context, reveal)
57704                 .on('done', function() {
57705                     entered.filter(function(d) {
57706                         return d.title === s.title;
57707                     }).classed('finished', true);
57708                     enter(steps[i + 1]);
57709                 });
57710             return s;
57711         });
57712
57713         steps[steps.length - 1].on('startEditing', function() {
57714             curtain.remove();
57715             navwrap.remove();
57716             selectAll('#map .layer-background').style('opacity', opacity);
57717             context.connection().toggle(true).reset().loadedTiles(loadedTiles);
57718             context.history().reset().merge(values(baseEntities));
57719             context.background().baseLayerSource(background);
57720             if (history) context.history().fromJSON(history, false);
57721             context.map().centerZoom(center, zoom$$1);
57722             window.location.replace(hash);
57723             context.inIntro(false);
57724         });
57725
57726         var navwrap = selection$$1
57727             .append('div')
57728             .attr('class', 'intro-nav-wrap fillD');
57729
57730         var buttonwrap = navwrap
57731             .append('div')
57732             .attr('class', 'joined')
57733             .selectAll('button.step');
57734
57735         var entered = buttonwrap
57736             .data(steps)
57737             .enter()
57738             .append('button')
57739             .attr('class', 'step')
57740             .on('click', enter);
57741
57742         entered
57743             .append('label')
57744             .text(function(d) { return t(d.title); });
57745
57746         entered
57747             .append('span')
57748             .attr('class', 'status')
57749             .text(' - ' + t('intro.done'));
57750
57751         enter(steps[0]);
57752
57753
57754         function enter(newStep) {
57755             if (step) { step.exit(); }
57756
57757             context.enter(modeBrowse$$1(context));
57758
57759             step = newStep;
57760             step.enter();
57761
57762             entered.classed('active', function(d) {
57763                 return d.title === step.title;
57764             });
57765         }
57766
57767     }
57768
57769
57770     return intro;
57771 }
57772
57773 function uiHelp(context) {
57774     var key = 'H';
57775
57776     var docKeys = [
57777         'help.help',
57778         'help.editing_saving',
57779         'help.roads',
57780         'help.gps',
57781         'help.imagery',
57782         'help.addresses',
57783         'help.inspector',
57784         'help.buildings',
57785         'help.relations'];
57786
57787     var docs = docKeys.map(function(key) {
57788         var text$$1 = t(key);
57789         return {
57790             title: text$$1.split('\n')[0].replace('#', '').trim(),
57791             html: marked(text$$1.split('\n').slice(1).join('\n'))
57792         };
57793     });
57794
57795
57796     function help(selection$$1) {
57797
57798         function hide() {
57799             setVisible(false);
57800         }
57801
57802
57803         function toggle() {
57804             if (event) event.preventDefault();
57805             tooltipBehavior.hide(button);
57806             setVisible(!button.classed('active'));
57807         }
57808
57809
57810         function setVisible(show) {
57811             if (show !== shown) {
57812                 button.classed('active', show);
57813                 shown = show;
57814
57815                 if (show) {
57816                     selection$$1.on('mousedown.help-inside', function() {
57817                         return event.stopPropagation();
57818                     });
57819                     pane.style('display', 'block')
57820                         .style('right', '-500px')
57821                         .transition()
57822                         .duration(200)
57823                         .style('right', '0px');
57824                 } else {
57825                     pane.style('right', '0px')
57826                         .transition()
57827                         .duration(200)
57828                         .style('right', '-500px')
57829                         .on('end', function() {
57830                             select(this).style('display', 'none');
57831                         });
57832                     selection$$1.on('mousedown.help-inside', null);
57833                 }
57834             }
57835         }
57836
57837
57838         function clickHelp(d, i) {
57839             pane.property('scrollTop', 0);
57840             doctitle.html(d.title);
57841             body.html(d.html);
57842             body.selectAll('a')
57843                 .attr('target', '_blank');
57844             menuItems.classed('selected', function(m) {
57845                 return m.title === d.title;
57846             });
57847
57848             nav.html('');
57849
57850             if (i > 0) {
57851                 var prevLink = nav.append('a')
57852                     .attr('class', 'previous')
57853                     .on('click', function() {
57854                         clickHelp(docs[i - 1], i - 1);
57855                     });
57856                 prevLink.append('span').html('&#9668; ' + docs[i - 1].title);
57857             }
57858             if (i < docs.length - 1) {
57859                 var nextLink = nav.append('a')
57860                     .attr('class', 'next')
57861                     .on('click', function() {
57862                         clickHelp(docs[i + 1], i + 1);
57863                     });
57864                 nextLink.append('span').html(docs[i + 1].title + ' &#9658;');
57865             }
57866         }
57867
57868
57869         function clickWalkthrough() {
57870             select(document.body).call(uiIntro(context));
57871             setVisible(false);
57872         }
57873
57874
57875         var pane = selection$$1.append('div')
57876                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
57877             tooltipBehavior = tooltip()
57878                 .placement((textDirection === 'rtl') ? 'right' : 'left')
57879                 .html(true)
57880                 .title(uiTooltipHtml(t('help.title'), key)),
57881             button = selection$$1.append('button')
57882                 .attr('tabindex', -1)
57883                 .on('click', toggle)
57884                 .call(svgIcon('#icon-help', 'light'))
57885                 .call(tooltipBehavior),
57886             shown = false;
57887
57888
57889         var toc = pane.append('ul')
57890             .attr('class', 'toc');
57891
57892         var menuItems = toc.selectAll('li')
57893             .data(docs)
57894             .enter()
57895             .append('li')
57896             .append('a')
57897             .html(function(d) { return d.title; })
57898             .on('click', clickHelp);
57899
57900         toc.append('li')
57901             .attr('class','walkthrough')
57902             .append('a')
57903             .text(t('splash.walkthrough'))
57904             .on('click', clickWalkthrough);
57905
57906         var content = pane.append('div')
57907             .attr('class', 'left-content');
57908
57909         var doctitle = content.append('h2')
57910             .text(t('help.title'));
57911
57912         var body = content.append('div')
57913             .attr('class', 'body');
57914
57915         var nav = content.append('div')
57916             .attr('class', 'nav');
57917
57918         clickHelp(docs[0], 0);
57919
57920         var keybinding = d3keybinding('help')
57921             .on(key, toggle)
57922             .on('B', hide)
57923             .on('F', hide);
57924
57925         select(document)
57926             .call(keybinding);
57927
57928         context.surface().on('mousedown.help-outside', hide);
57929         context.container().on('mousedown.help-outside', hide);
57930     }
57931
57932     return help;
57933 }
57934
57935 function uiInfo(context) {
57936     var key = uiCmd('⌘I'),
57937         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
57938         isHidden = true;
57939
57940
57941     function info(selection$$1) {
57942
57943         function radiansToMeters(r) {
57944             // using WGS84 authalic radius (6371007.1809 m)
57945             return r * 6371007.1809;
57946         }
57947
57948         function steradiansToSqmeters(r) {
57949             // http://gis.stackexchange.com/a/124857/40446
57950             return r / (4 * Math.PI) * 510065621724000;
57951         }
57952
57953
57954         function toLineString(feature) {
57955             if (feature.type === 'LineString') return feature;
57956
57957             var result = { type: 'LineString', coordinates: [] };
57958             if (feature.type === 'Polygon') {
57959                 result.coordinates = feature.coordinates[0];
57960             } else if (feature.type === 'MultiPolygon') {
57961                 result.coordinates = feature.coordinates[0][0];
57962             }
57963
57964             return result;
57965         }
57966
57967
57968         function displayLength(m) {
57969             var d = m * (isImperial ? 3.28084 : 1),
57970                 p, unit;
57971
57972             if (isImperial) {
57973                 if (d >= 5280) {
57974                     d /= 5280;
57975                     unit = 'mi';
57976                 } else {
57977                     unit = 'ft';
57978                 }
57979             } else {
57980                 if (d >= 1000) {
57981                     d /= 1000;
57982                     unit = 'km';
57983                 } else {
57984                     unit = 'm';
57985                 }
57986             }
57987
57988             // drop unnecessary precision
57989             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
57990
57991             return String(d.toFixed(p)) + ' ' + unit;
57992         }
57993
57994
57995         function displayArea(m2) {
57996             var d = m2 * (isImperial ? 10.7639111056 : 1),
57997                 d1, d2, p1, p2, unit1, unit2;
57998
57999             if (isImperial) {
58000                 if (d >= 6969600) {     // > 0.25mi² show mi²
58001                     d1 = d / 27878400;
58002                     unit1 = 'mi²';
58003                 } else {
58004                     d1 = d;
58005                     unit1 = 'ft²';
58006                 }
58007
58008                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
58009                     d2 = d / 43560;
58010                     unit2 = 'ac';
58011                 }
58012
58013             } else {
58014                 if (d >= 250000) {    // > 0.25km² show km²
58015                     d1 = d / 1000000;
58016                     unit1 = 'km²';
58017                 } else {
58018                     d1 = d;
58019                     unit1 = 'm²';
58020                 }
58021
58022                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
58023                     d2 = d / 10000;
58024                     unit2 = 'ha';
58025                 }
58026             }
58027
58028             // drop unnecessary precision
58029             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
58030             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
58031
58032             return String(d1.toFixed(p1)) + ' ' + unit1 +
58033                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
58034         }
58035
58036
58037         function redraw() {
58038             if (isHidden) return;
58039
58040             var resolver = context.graph(),
58041                 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
58042                 singular = selected.length === 1 ? selected[0] : null,
58043                 extent$$1 = geoExtent$$1(),
58044                 entity;
58045
58046             wrap.html('');
58047             wrap.append('h4')
58048                 .attr('class', 'infobox-heading fillD')
58049                 .text(singular || t('infobox.selected', { n: selected.length }));
58050
58051             if (!selected.length) return;
58052
58053             var center;
58054             for (var i = 0; i < selected.length; i++) {
58055                 entity = context.entity(selected[i]);
58056                 extent$$1._extend(entity.extent(resolver));
58057             }
58058             center = extent$$1.center();
58059
58060
58061             var list = wrap.append('ul');
58062
58063             // multiple features, just display extent center..
58064             if (!singular) {
58065                 list.append('li')
58066                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
58067                 return;
58068             }
58069
58070             // single feature, display details..
58071             if (!entity) return;
58072             var geometry = entity.geometry(resolver);
58073
58074             if (geometry === 'line' || geometry === 'area') {
58075                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
58076                     feature = entity.asGeoJSON(resolver),
58077                     length = radiansToMeters(d3GeoLength(toLineString(feature))),
58078                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
58079                     centroid = d3GeoCentroid(feature);
58080
58081                 list.append('li')
58082                     .text(t('infobox.geometry') + ': ' +
58083                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
58084
58085                 if (closed) {
58086                     var area$$1 = steradiansToSqmeters(entity.area(resolver));
58087                     list.append('li')
58088                         .text(t('infobox.area') + ': ' + displayArea(area$$1));
58089                 }
58090
58091                 list.append('li')
58092                     .text(lengthLabel + ': ' + displayLength(length));
58093
58094                 list.append('li')
58095                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
58096
58097
58098                 var toggle  = isImperial ? 'imperial' : 'metric';
58099                 wrap.append('a')
58100                     .text(t('infobox.' + toggle))
58101                     .attr('href', '#')
58102                     .attr('class', 'button')
58103                     .on('click', function() {
58104                         event.preventDefault();
58105                         isImperial = !isImperial;
58106                         redraw();
58107                     });
58108
58109             } else {
58110                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
58111
58112                 list.append('li')
58113                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
58114
58115                 list.append('li')
58116                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
58117             }
58118         }
58119
58120
58121         function toggle() {
58122             if (event) {
58123                 event.preventDefault();
58124             }
58125
58126             isHidden = !isHidden;
58127
58128             if (isHidden) {
58129                 wrap
58130                     .style('display', 'block')
58131                     .style('opacity', 1)
58132                     .transition()
58133                     .duration(200)
58134                     .style('opacity', 0)
58135                     .on('end', function() {
58136                         select(this).style('display', 'none');
58137                     });
58138             } else {
58139                 wrap
58140                     .style('display', 'block')
58141                     .style('opacity', 0)
58142                     .transition()
58143                     .duration(200)
58144                     .style('opacity', 1)
58145                     .on('end', function() {
58146                         redraw();
58147                     });
58148             }
58149         }
58150
58151
58152         var wrap = selection$$1.selectAll('.infobox')
58153             .data([0]);
58154
58155         wrap = wrap.enter()
58156             .append('div')
58157             .attr('class', 'infobox fillD2')
58158             .style('display', (isHidden ? 'none' : 'block'))
58159             .merge(wrap);
58160
58161         context.map()
58162             .on('drawn.info', redraw);
58163
58164         redraw();
58165
58166         var keybinding = d3keybinding('info')
58167             .on(key, toggle);
58168
58169         select(document)
58170             .call(keybinding);
58171     }
58172
58173     return info;
58174 }
58175
58176 function uiMapData(context) {
58177     var key = 'F',
58178         features = context.features().keys(),
58179         layers = context.layers(),
58180         fills = ['wireframe', 'partial', 'full'],
58181         fillDefault = context.storage('area-fill') || 'partial',
58182         fillSelected = fillDefault;
58183
58184
58185     function map_data(selection$$1) {
58186
58187         function showsFeature(d) {
58188             return context.features().enabled(d);
58189         }
58190
58191
58192         function autoHiddenFeature(d) {
58193             return context.features().autoHidden(d);
58194         }
58195
58196
58197         function clickFeature(d) {
58198             context.features().toggle(d);
58199             update();
58200         }
58201
58202
58203         function showsFill(d) {
58204             return fillSelected === d;
58205         }
58206
58207
58208         function setFill(d) {
58209             lodash.each(fills, function(opt) {
58210                 context.surface().classed('fill-' + opt, Boolean(opt === d));
58211             });
58212
58213             fillSelected = d;
58214             if (d !== 'wireframe') {
58215                 fillDefault = d;
58216                 context.storage('area-fill', d);
58217             }
58218             update();
58219         }
58220
58221
58222         function showsLayer(which) {
58223             var layer = layers.layer(which);
58224             if (layer) {
58225                 return layer.enabled();
58226             }
58227             return false;
58228         }
58229
58230
58231         function setLayer(which, enabled) {
58232             var layer = layers.layer(which);
58233             if (layer) {
58234                 layer.enabled(enabled);
58235                 update();
58236             }
58237         }
58238
58239
58240         function toggleLayer(which) {
58241             setLayer(which, !showsLayer(which));
58242         }
58243
58244
58245         function clickGpx() {
58246             toggleLayer('gpx');
58247         }
58248
58249
58250         function clickMapillaryImages() {
58251             toggleLayer('mapillary-images');
58252             if (!showsLayer('mapillary-images')) {
58253                 setLayer('mapillary-signs', false);
58254             }
58255         }
58256
58257
58258         function clickMapillarySigns() {
58259             toggleLayer('mapillary-signs');
58260         }
58261
58262
58263         function drawMapillaryItems(selection$$1) {
58264             var mapillaryImages = layers.layer('mapillary-images'),
58265                 mapillarySigns = layers.layer('mapillary-signs'),
58266                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
58267                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
58268                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
58269                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
58270
58271             var mapillaryList = selection$$1
58272                 .selectAll('.layer-list-mapillary')
58273                 .data([0]);
58274
58275             mapillaryList = mapillaryList.enter()
58276                 .append('ul')
58277                 .attr('class', 'layer-list layer-list-mapillary')
58278                 .merge(mapillaryList);
58279
58280
58281             var mapillaryImageLayerItem = mapillaryList
58282                 .selectAll('.list-item-mapillary-images')
58283                 .data(supportsMapillaryImages ? [0] : []);
58284
58285             mapillaryImageLayerItem.exit()
58286                 .remove();
58287
58288             var enterImages = mapillaryImageLayerItem.enter()
58289                 .append('li')
58290                 .attr('class', 'list-item-mapillary-images');
58291
58292             var labelImages = enterImages
58293                 .append('label')
58294                 .call(tooltip()
58295                     .title(t('mapillary_images.tooltip'))
58296                     .placement('top'));
58297
58298             labelImages
58299                 .append('input')
58300                 .attr('type', 'checkbox')
58301                 .on('change', clickMapillaryImages);
58302
58303             labelImages
58304                 .append('span')
58305                 .text(t('mapillary_images.title'));
58306
58307
58308             var mapillarySignLayerItem = mapillaryList
58309                 .selectAll('.list-item-mapillary-signs')
58310                 .data(supportsMapillarySigns ? [0] : []);
58311
58312             mapillarySignLayerItem.exit()
58313                 .remove();
58314
58315             var enterSigns = mapillarySignLayerItem.enter()
58316                 .append('li')
58317                 .attr('class', 'list-item-mapillary-signs');
58318
58319             var labelSigns = enterSigns
58320                 .append('label')
58321                 .call(tooltip()
58322                     .title(t('mapillary_signs.tooltip'))
58323                     .placement('top'));
58324
58325             labelSigns
58326                 .append('input')
58327                 .attr('type', 'checkbox')
58328                 .on('change', clickMapillarySigns);
58329
58330             labelSigns
58331                 .append('span')
58332                 .text(t('mapillary_signs.title'));
58333
58334
58335             // Updates
58336             mapillaryImageLayerItem = mapillaryImageLayerItem
58337                 .merge(enterImages);
58338
58339             mapillaryImageLayerItem
58340                 .classed('active', showsMapillaryImages)
58341                 .selectAll('input')
58342                 .property('checked', showsMapillaryImages);
58343
58344
58345             mapillarySignLayerItem = mapillarySignLayerItem
58346                 .merge(enterSigns);
58347
58348             mapillarySignLayerItem
58349                 .classed('active', showsMapillarySigns)
58350                 .selectAll('input')
58351                 .property('disabled', !showsMapillaryImages)
58352                 .property('checked', showsMapillarySigns);
58353
58354             mapillarySignLayerItem
58355                 .selectAll('label')
58356                 .classed('deemphasize', !showsMapillaryImages);
58357         }
58358
58359
58360         function drawGpxItem(selection$$1) {
58361             var gpx = layers.layer('gpx'),
58362                 hasGpx = gpx && gpx.hasGpx(),
58363                 showsGpx = hasGpx && gpx.enabled();
58364
58365             var gpxLayerItem = selection$$1
58366                 .selectAll('.layer-list-gpx')
58367                 .data(gpx ? [0] : []);
58368
58369             // Exit
58370             gpxLayerItem.exit()
58371                 .remove();
58372
58373             // Enter
58374             var enter = gpxLayerItem.enter()
58375                 .append('ul')
58376                 .attr('class', 'layer-list layer-list-gpx')
58377                 .append('li')
58378                 .classed('list-item-gpx', true);
58379
58380             enter
58381                 .append('button')
58382                 .attr('class', 'list-item-gpx-extent')
58383                 .call(tooltip()
58384                     .title(t('gpx.zoom'))
58385                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
58386                 .on('click', function() {
58387                     event.preventDefault();
58388                     event.stopPropagation();
58389                     gpx.fitZoom();
58390                 })
58391                 .call(svgIcon('#icon-search'));
58392
58393             enter
58394                 .append('button')
58395                 .attr('class', 'list-item-gpx-browse')
58396                 .call(tooltip()
58397                     .title(t('gpx.browse'))
58398                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
58399                 .on('click', function() {
58400                     select(document.createElement('input'))
58401                         .attr('type', 'file')
58402                         .on('change', function() {
58403                             gpx.files(event.target.files);
58404                         })
58405                         .node().click();
58406                 })
58407                 .call(svgIcon('#icon-geolocate'));
58408
58409             var labelGpx = enter
58410                 .append('label')
58411                 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
58412
58413             labelGpx
58414                 .append('input')
58415                 .attr('type', 'checkbox')
58416                 .on('change', clickGpx);
58417
58418             labelGpx
58419                 .append('span')
58420                 .text(t('gpx.local_layer'));
58421
58422
58423             // Update
58424             gpxLayerItem = gpxLayerItem
58425                 .merge(enter);
58426
58427             gpxLayerItem
58428                 .classed('active', showsGpx)
58429                 .selectAll('input')
58430                 .property('disabled', !hasGpx)
58431                 .property('checked', showsGpx);
58432
58433             gpxLayerItem
58434                 .selectAll('label')
58435                 .classed('deemphasize', !hasGpx);
58436         }
58437
58438
58439         function drawList(selection$$1, data, type, name, change, active$$1) {
58440             var items = selection$$1.selectAll('li')
58441                 .data(data);
58442
58443             // Exit
58444             items.exit()
58445                 .remove();
58446
58447             // Enter
58448             var enter = items.enter()
58449                 .append('li')
58450                 .attr('class', 'layer')
58451                 .call(tooltip()
58452                     .html(true)
58453                     .title(function(d) {
58454                         var tip = t(name + '.' + d + '.tooltip'),
58455                             key = (d === 'wireframe' ? 'W' : null);
58456
58457                         if (name === 'feature' && autoHiddenFeature(d)) {
58458                             tip += '<div>' + t('map_data.autohidden') + '</div>';
58459                         }
58460                         return uiTooltipHtml(tip, key);
58461                     })
58462                     .placement('top')
58463                 );
58464
58465             var label = enter
58466                 .append('label');
58467
58468             label
58469                 .append('input')
58470                 .attr('type', type)
58471                 .attr('name', name)
58472                 .on('change', change);
58473
58474             label
58475                 .append('span')
58476                 .text(function(d) { return t(name + '.' + d + '.description'); });
58477
58478             // Update
58479             items = items
58480                 .merge(enter);
58481
58482             items
58483                 .classed('active', active$$1)
58484                 .selectAll('input')
58485                 .property('checked', active$$1)
58486                 .property('indeterminate', function(d) {
58487                     return (name === 'feature' && autoHiddenFeature(d));
58488                 });
58489         }
58490
58491
58492         function update() {
58493             dataLayerContainer.call(drawMapillaryItems);
58494             dataLayerContainer.call(drawGpxItem);
58495
58496             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
58497             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
58498         }
58499
58500
58501         function hidePanel() {
58502             setVisible(false);
58503         }
58504
58505
58506         function togglePanel() {
58507             if (event) event.preventDefault();
58508             tooltipBehavior.hide(button);
58509             setVisible(!button.classed('active'));
58510         }
58511
58512
58513         function toggleWireframe() {
58514             if (event) {
58515                 event.preventDefault();
58516                 event.stopPropagation();
58517             }
58518             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
58519             context.map().pan([0,0]);  // trigger a redraw
58520         }
58521
58522
58523         function setVisible(show) {
58524             if (show !== shown) {
58525                 button.classed('active', show);
58526                 shown = show;
58527
58528                 if (show) {
58529                     update();
58530                     selection$$1.on('mousedown.map_data-inside', function() {
58531                         return event.stopPropagation();
58532                     });
58533                     content.style('display', 'block')
58534                         .style('right', '-300px')
58535                         .transition()
58536                         .duration(200)
58537                         .style('right', '0px');
58538                 } else {
58539                     content.style('display', 'block')
58540                         .style('right', '0px')
58541                         .transition()
58542                         .duration(200)
58543                         .style('right', '-300px')
58544                         .on('end', function() {
58545                             select(this).style('display', 'none');
58546                         });
58547                     selection$$1.on('mousedown.map_data-inside', null);
58548                 }
58549             }
58550         }
58551
58552
58553         var content = selection$$1
58554                 .append('div')
58555                 .attr('class', 'fillL map-overlay col3 content hide'),
58556             tooltipBehavior = tooltip()
58557                 .placement((textDirection === 'rtl') ? 'right' : 'left')
58558                 .html(true)
58559                 .title(uiTooltipHtml(t('map_data.description'), key)),
58560             button = selection$$1
58561                 .append('button')
58562                 .attr('tabindex', -1)
58563                 .on('click', togglePanel)
58564                 .call(svgIcon('#icon-data', 'light'))
58565                 .call(tooltipBehavior),
58566             shown = false;
58567
58568         content
58569             .append('h4')
58570             .text(t('map_data.title'));
58571
58572
58573         // data layers
58574         content
58575             .append('a')
58576             .text(t('map_data.data_layers'))
58577             .attr('href', '#')
58578             .classed('hide-toggle', true)
58579             .classed('expanded', true)
58580             .on('click', function() {
58581                 var exp = select(this).classed('expanded');
58582                 dataLayerContainer.style('display', exp ? 'none' : 'block');
58583                 select(this).classed('expanded', !exp);
58584                 event.preventDefault();
58585             });
58586
58587         var dataLayerContainer = content
58588             .append('div')
58589             .attr('class', 'data-data-layers')
58590             .style('display', 'block');
58591
58592
58593         // area fills
58594         content
58595             .append('a')
58596             .text(t('map_data.fill_area'))
58597             .attr('href', '#')
58598             .classed('hide-toggle', true)
58599             .classed('expanded', false)
58600             .on('click', function() {
58601                 var exp = select(this).classed('expanded');
58602                 fillContainer.style('display', exp ? 'none' : 'block');
58603                 select(this).classed('expanded', !exp);
58604                 event.preventDefault();
58605             });
58606
58607         var fillContainer = content
58608             .append('div')
58609             .attr('class', 'data-area-fills')
58610             .style('display', 'none');
58611
58612         var fillList = fillContainer
58613             .append('ul')
58614             .attr('class', 'layer-list layer-fill-list');
58615
58616
58617         // feature filters
58618         content
58619             .append('a')
58620             .text(t('map_data.map_features'))
58621             .attr('href', '#')
58622             .classed('hide-toggle', true)
58623             .classed('expanded', false)
58624             .on('click', function() {
58625                 var exp = select(this).classed('expanded');
58626                 featureContainer.style('display', exp ? 'none' : 'block');
58627                 select(this).classed('expanded', !exp);
58628                 event.preventDefault();
58629             });
58630
58631         var featureContainer = content
58632             .append('div')
58633             .attr('class', 'data-feature-filters')
58634             .style('display', 'none');
58635
58636         var featureList = featureContainer
58637             .append('ul')
58638             .attr('class', 'layer-list layer-feature-list');
58639
58640
58641         context.features()
58642             .on('change.map_data-update', update);
58643
58644         setFill(fillDefault);
58645
58646         var keybinding = d3keybinding('features')
58647             .on(key, togglePanel)
58648             .on('W', toggleWireframe)
58649             .on('B', hidePanel)
58650             .on('H', hidePanel);
58651
58652         select(document)
58653             .call(keybinding);
58654
58655         context.surface().on('mousedown.map_data-outside', hidePanel);
58656         context.container().on('mousedown.map_data-outside', hidePanel);
58657     }
58658
58659
58660     return map_data;
58661 }
58662
58663 function uiModes(context) {
58664     var modes = [
58665         modeAddPoint$$1(context),
58666         modeAddLine$$1(context),
58667         modeAddArea$$1(context)
58668     ];
58669
58670
58671     function editable() {
58672         return context.editable() && context.mode().id !== 'save';
58673     }
58674
58675
58676     return function(selection$$1) {
58677         var buttons = selection$$1.selectAll('button.add-button')
58678             .data(modes);
58679
58680         buttons = buttons.enter()
58681             .append('button')
58682             .attr('tabindex', -1)
58683             .attr('class', function(mode) { return mode.id + ' add-button col4'; })
58684             .on('click.mode-buttons', function(mode) {
58685                 if (mode.id === context.mode().id) {
58686                     context.enter(modeBrowse$$1(context));
58687                 } else {
58688                     context.enter(mode);
58689                 }
58690             })
58691             .call(tooltip()
58692                 .placement('bottom')
58693                 .html(true)
58694                 .title(function(mode) {
58695                     return uiTooltipHtml(mode.description, mode.key);
58696                 })
58697             );
58698
58699         context.map()
58700             .on('move.modes', lodash.debounce(update, 500));
58701
58702         context
58703             .on('enter.modes', update);
58704
58705         buttons
58706             .each(function(d) {
58707                 select(this)
58708                     .call(svgIcon('#icon-' + d.button, 'pre-text'));
58709             });
58710
58711         buttons
58712             .append('span')
58713             .attr('class', 'label')
58714             .text(function(mode) { return mode.title; });
58715
58716         context
58717             .on('enter.editor', function(entered) {
58718                 selection$$1.selectAll('button.add-button')
58719                     .classed('active', function(mode) { return entered.button === mode.button; });
58720                 context.container()
58721                     .classed('mode-' + entered.id, true);
58722             });
58723
58724         context
58725             .on('exit.editor', function(exited) {
58726                 context.container()
58727                     .classed('mode-' + exited.id, false);
58728             });
58729
58730         var keybinding = d3keybinding('mode-buttons');
58731
58732         modes.forEach(function(m) {
58733             keybinding.on(m.key, function() {
58734                 if (editable()) context.enter(m);
58735             });
58736         });
58737
58738         select(document)
58739             .call(keybinding);
58740
58741
58742         function update() {
58743             selection$$1.selectAll('button.add-button')
58744                 .property('disabled', !editable());
58745         }
58746     };
58747 }
58748
58749 function uiRestore(context) {
58750
58751     return function(selection) {
58752         if (!context.history().lock() || !context.history().restorableChanges())
58753             return;
58754
58755         var modalSelection = uiModal(selection, true);
58756
58757         modalSelection.select('.modal')
58758             .attr('class', 'modal fillL col6');
58759
58760         var introModal = modalSelection.select('.content');
58761
58762         introModal
58763             .attr('class','cf');
58764
58765         introModal
58766             .append('div')
58767             .attr('class', 'modal-section')
58768             .append('h3')
58769             .text(t('restore.heading'));
58770
58771         introModal
58772             .append('div')
58773             .attr('class','modal-section')
58774             .append('p')
58775             .text(t('restore.description'));
58776
58777         var buttonWrap = introModal
58778             .append('div')
58779             .attr('class', 'modal-actions cf');
58780
58781         var restore = buttonWrap
58782             .append('button')
58783             .attr('class', 'restore col6')
58784             .text(t('restore.restore'))
58785             .on('click', function() {
58786                 context.history().restore();
58787                 modalSelection.remove();
58788             });
58789
58790         buttonWrap
58791             .append('button')
58792             .attr('class', 'reset col6')
58793             .text(t('restore.reset'))
58794             .on('click', function() {
58795                 context.history().clearSaved();
58796                 modalSelection.remove();
58797             });
58798
58799         restore.node().focus();
58800     };
58801 }
58802
58803 function uiSave(context) {
58804     var history = context.history(),
58805         key = uiCmd('⌘S');
58806
58807
58808     function saving() {
58809         return context.mode().id === 'save';
58810     }
58811
58812
58813     function save() {
58814         event.preventDefault();
58815         if (!context.inIntro() && !saving() && history.hasChanges()) {
58816             context.enter(modeSave$$1(context));
58817         }
58818     }
58819
58820
58821     function getBackground(numChanges) {
58822         var step;
58823         if (numChanges === 0) {
58824             return null;
58825         } else if (numChanges <= 50) {
58826             step = numChanges / 50;
58827             return interpolateRgb('#fff', '#ff8')(step);  // white -> yellow
58828         } else {
58829             step = Math.min((numChanges - 50) / 50, 1.0);
58830             return interpolateRgb('#ff8', '#f88')(step);  // yellow -> red
58831         }
58832     }
58833
58834
58835     return function(selection$$1) {
58836         var tooltipBehavior = tooltip()
58837             .placement('bottom')
58838             .html(true)
58839             .title(uiTooltipHtml(t('save.no_changes'), key));
58840
58841         var button = selection$$1
58842             .append('button')
58843             .attr('class', 'save col12 disabled')
58844             .attr('tabindex', -1)
58845             .on('click', save)
58846             .call(tooltipBehavior);
58847
58848         button
58849             .append('span')
58850             .attr('class', 'label')
58851             .text(t('save.title'));
58852
58853         button
58854             .append('span')
58855             .attr('class', 'count')
58856             .text('0');
58857
58858         var keybinding = d3keybinding('undo-redo')
58859             .on(key, save, true);
58860
58861         select(document)
58862             .call(keybinding);
58863
58864         var numChanges = 0;
58865
58866         context.history()
58867             .on('change.save', function() {
58868                 var _ = history.difference().summary().length;
58869                 if (_ === numChanges)
58870                     return;
58871                 numChanges = _;
58872
58873                 tooltipBehavior.title(uiTooltipHtml(
58874                     t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key));
58875
58876                 var background = getBackground(numChanges);
58877
58878                 button
58879                     .classed('disabled', numChanges === 0)
58880                     .classed('has-count', numChanges > 0)
58881                     .style('background', background);
58882
58883                 button.select('span.count')
58884                     .text(numChanges)
58885                     .style('background', background)
58886                     .style('border-color', background);
58887             });
58888
58889         context
58890             .on('enter.save', function() {
58891                 button.property('disabled', saving());
58892                 if (saving()) button.call(tooltipBehavior.hide);
58893             });
58894     };
58895 }
58896
58897 function uiScale(context) {
58898     var projection = context.projection,
58899         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
58900         maxLength = 180,
58901         tickHeight = 8;
58902
58903
58904     function scaleDefs(loc1, loc2) {
58905         var lat = (loc2[1] + loc1[1]) / 2,
58906             conversion = (isImperial ? 3.28084 : 1),
58907             dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
58908             scale = { dist: 0, px: 0, text: '' },
58909             buckets, i, val, dLon;
58910
58911         if (isImperial) {
58912             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
58913         } else {
58914             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
58915         }
58916
58917         // determine a user-friendly endpoint for the scale
58918         for (i = 0; i < buckets.length; i++) {
58919             val = buckets[i];
58920             if (dist >= val) {
58921                 scale.dist = Math.floor(dist / val) * val;
58922                 break;
58923             } else {
58924                 scale.dist = +dist.toFixed(2);
58925             }
58926         }
58927
58928         dLon = geoMetersToLon(scale.dist / conversion, lat);
58929         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
58930
58931         if (isImperial) {
58932             if (scale.dist >= 5280) {
58933                 scale.dist /= 5280;
58934                 scale.text = String(scale.dist) + ' mi';
58935             } else {
58936                 scale.text = String(scale.dist) + ' ft';
58937             }
58938         } else {
58939             if (scale.dist >= 1000) {
58940                 scale.dist /= 1000;
58941                 scale.text = String(scale.dist) + ' km';
58942             } else {
58943                 scale.text = String(scale.dist) + ' m';
58944             }
58945         }
58946
58947         return scale;
58948     }
58949
58950
58951     function update(selection) {
58952         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
58953         var dims = context.map().dimensions(),
58954             loc1 = projection.invert([0, dims[1]]),
58955             loc2 = projection.invert([maxLength, dims[1]]),
58956             scale = scaleDefs(loc1, loc2);
58957
58958         selection.select('#scalepath')
58959             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
58960
58961         selection.select('#scaletext')
58962             .attr('x', scale.px + 8)
58963             .attr('y', tickHeight)
58964             .text(scale.text);
58965     }
58966
58967
58968     return function(selection) {
58969         function switchUnits() {
58970             isImperial = !isImperial;
58971             selection.call(update);
58972         }
58973
58974         var g = selection.append('svg')
58975             .attr('id', 'scale')
58976             .on('click', switchUnits)
58977             .append('g')
58978             .attr('transform', 'translate(10,11)');
58979
58980         g.append('path').attr('id', 'scalepath');
58981         g.append('text').attr('id', 'scaletext');
58982
58983         selection.call(update);
58984
58985         context.map().on('move.scale', function() {
58986             update(selection);
58987         });
58988     };
58989 }
58990
58991 var pair_1 = pair;
58992 function search(x, dims, r) {
58993   if (!dims) dims = 'NSEW';
58994   if (typeof x !== 'string') return { val: null, regex: r };
58995   r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
58996   var m = r.exec(x);
58997   if (!m) return { val: null, regex: r };
58998   else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
58999   else return {
59000     val: (((m[1]) ? parseFloat(m[1]) : 0) +
59001           ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
59002           ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
59003           ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
59004     regex: r,
59005     raw: m[0],
59006     dim: m[4]
59007   };
59008 }
59009
59010 function pair(x, dims) {
59011   x = x.trim();
59012   var one = search(x, dims);
59013   if (one.val === null) return null;
59014   var two = search(x, dims, one.regex);
59015   if (two.val === null) return null;
59016   // null if one/two are not contiguous.
59017   if (one.raw + two.raw !== x) return null;
59018   if (one.dim) {
59019     return swapdim(one.val, two.val, one.dim);
59020   } else {
59021     return [one.val, two.val];
59022   }
59023 }
59024
59025 function swapdim(a, b, dim) {
59026   if (dim === 'N' || dim === 'S') return [a, b];
59027   if (dim === 'W' || dim === 'E') return [b, a];
59028 }
59029
59030 function uiFeatureList(context) {
59031     var geocodeResults;
59032
59033
59034     function featureList(selection$$1) {
59035         var header = selection$$1.append('div')
59036             .attr('class', 'header fillL cf');
59037
59038         header.append('h3')
59039             .text(t('inspector.feature_list'));
59040
59041         var searchWrap = selection$$1.append('div')
59042             .attr('class', 'search-header');
59043
59044         var search = searchWrap.append('input')
59045             .attr('placeholder', t('inspector.search'))
59046             .attr('type', 'search')
59047             .on('keypress', keypress)
59048             .on('input', inputevent);
59049
59050         searchWrap
59051             .call(svgIcon('#icon-search', 'pre-text'));
59052
59053         var listWrap = selection$$1.append('div')
59054             .attr('class', 'inspector-body');
59055
59056         var list = listWrap.append('div')
59057             .attr('class', 'feature-list cf');
59058
59059         context
59060             .on('exit.feature-list', clearSearch);
59061         context.map()
59062             .on('drawn.feature-list', mapDrawn);
59063
59064
59065         function keypress() {
59066             var q = search.property('value'),
59067                 items = list.selectAll('.feature-list-item');
59068             if (event.keyCode === 13 && q.length && items.size()) {
59069                 click(items.datum());
59070             }
59071         }
59072
59073
59074         function inputevent() {
59075             geocodeResults = undefined;
59076             drawList();
59077         }
59078
59079
59080         function clearSearch() {
59081             search.property('value', '');
59082             drawList();
59083         }
59084
59085
59086         function mapDrawn(e) {
59087             if (e.full) {
59088                 drawList();
59089             }
59090         }
59091
59092
59093         function features() {
59094             var entities = {},
59095                 result = [],
59096                 graph = context.graph(),
59097                 q = search.property('value').toLowerCase();
59098
59099             if (!q) return result;
59100
59101             var idMatch = q.match(/^([nwr])([0-9]+)$/);
59102
59103             if (idMatch) {
59104                 result.push({
59105                     id: idMatch[0],
59106                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
59107                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
59108                     name: idMatch[2]
59109                 });
59110             }
59111
59112             var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
59113
59114             if (locationMatch) {
59115                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
59116                 result.push({
59117                     id: -1,
59118                     geometry: 'point',
59119                     type: t('inspector.location'),
59120                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
59121                     location: loc
59122                 });
59123             }
59124
59125             function addEntity(entity) {
59126                 if (entity.id in entities || result.length > 200)
59127                     return;
59128
59129                 entities[entity.id] = true;
59130
59131                 var name = utilDisplayName(entity) || '';
59132                 if (name.toLowerCase().indexOf(q) >= 0) {
59133                     var matched = context.presets().match(entity, graph),
59134                         type = (matched && matched.name()) || utilDisplayType(entity.id);
59135                     result.push({
59136                         id: entity.id,
59137                         entity: entity,
59138                         geometry: context.geometry(entity.id),
59139                         type: type,
59140                         name: name
59141                     });
59142                 }
59143
59144                 graph.parentRelations(entity).forEach(function(parent) {
59145                     addEntity(parent);
59146                 });
59147             }
59148
59149             var visible = context.surface().selectAll('.point, .line, .area').nodes();
59150             for (var i = 0; i < visible.length && result.length <= 200; i++) {
59151                 addEntity(visible[i].__data__);
59152             }
59153
59154             (geocodeResults || []).forEach(function(d) {
59155                 // https://github.com/openstreetmap/iD/issues/1890
59156                 if (d.osm_type && d.osm_id) {
59157                     result.push({
59158                         id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
59159                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
59160                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
59161                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
59162                         name: d.display_name,
59163                         extent: new geoExtent$$1(
59164                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
59165                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
59166                     });
59167                 }
59168             });
59169
59170             return result;
59171         }
59172
59173
59174         function drawList() {
59175             var value = search.property('value'),
59176                 results = features();
59177
59178             list.classed('filtered', value.length);
59179
59180             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
59181
59182             var resultsIndicator = list.selectAll('.no-results-item')
59183                 .data([0])
59184                 .enter().append('button')
59185                 .property('disabled', true)
59186                 .attr('class', 'no-results-item')
59187                 .call(svgIcon('#icon-alert', 'pre-text'));
59188
59189             resultsIndicator.append('span')
59190                 .attr('class', 'entity-name');
59191
59192             list.selectAll('.no-results-item .entity-name')
59193                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
59194
59195             list.selectAll('.geocode-item')
59196                 .data([0])
59197                 .enter().append('button')
59198                 .attr('class', 'geocode-item')
59199                 .on('click', geocode)
59200                 .append('div')
59201                 .attr('class', 'label')
59202                 .append('span')
59203                 .attr('class', 'entity-name')
59204                 .text(t('geocoder.search'));
59205
59206             list.selectAll('.no-results-item')
59207                 .style('display', (value.length && !results.length) ? 'block' : 'none');
59208
59209             list.selectAll('.geocode-item')
59210                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
59211
59212             list.selectAll('.feature-list-item')
59213                 .data([-1])
59214                 .remove();
59215
59216             var items = list.selectAll('.feature-list-item')
59217                 .data(results, function(d) { return d.id; });
59218
59219             var enter = items.enter()
59220                 .insert('button', '.geocode-item')
59221                 .attr('class', 'feature-list-item')
59222                 .on('mouseover', mouseover)
59223                 .on('mouseout', mouseout)
59224                 .on('click', click);
59225
59226             var label = enter
59227                 .append('div')
59228                 .attr('class', 'label');
59229
59230             label.each(function(d) {
59231                 select(this)
59232                     .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
59233             });
59234
59235             label.append('span')
59236                 .attr('class', 'entity-type')
59237                 .text(function(d) { return d.type; });
59238
59239             label.append('span')
59240                 .attr('class', 'entity-name')
59241                 .text(function(d) { return d.name; });
59242
59243             enter.style('opacity', 0)
59244                 .transition()
59245                 .style('opacity', 1);
59246
59247             items.order();
59248
59249             items.exit()
59250                 .remove();
59251         }
59252
59253
59254         function mouseover(d) {
59255             if (d.id === -1) return;
59256
59257             context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
59258                 .classed('hover', true);
59259         }
59260
59261
59262         function mouseout() {
59263             context.surface().selectAll('.hover')
59264                 .classed('hover', false);
59265         }
59266
59267
59268         function click(d) {
59269             event.preventDefault();
59270             if (d.location) {
59271                 context.map().centerZoom([d.location[1], d.location[0]], 20);
59272             }
59273             else if (d.entity) {
59274                 if (d.entity.type === 'node') {
59275                     context.map().center(d.entity.loc);
59276                 } else if (d.entity.type === 'way') {
59277                     var center = context.projection(context.map().center()),
59278                         edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
59279                     context.map().center(edge.loc);
59280                 }
59281                 context.enter(modeSelect(context, [d.entity.id]).suppressMenu(true));
59282             } else {
59283                 context.zoomToEntity(d.id);
59284             }
59285         }
59286
59287
59288         function geocode() {
59289             var searchVal = encodeURIComponent(search.property('value'));
59290             json('https://nominatim.openstreetmap.org/search/' + searchVal + '?limit=10&format=json', function(err, resp) {
59291                 geocodeResults = resp || [];
59292                 drawList();
59293             });
59294         }
59295     }
59296
59297
59298     return featureList;
59299 }
59300
59301 function uiPresetIcon() {
59302     var preset, geometry;
59303
59304
59305     function presetIcon(selection$$1) {
59306         selection$$1.each(render);
59307     }
59308
59309
59310     function render() {
59311         var selection$$1 = select(this),
59312             p = preset.apply(this, arguments),
59313             geom = geometry.apply(this, arguments),
59314             picon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
59315             isMaki = dataFeatureIcons.hasOwnProperty(picon + '-24');
59316
59317         if (picon === 'dentist') {
59318             isMaki = true;  // workaround for dentist icon missing in `maki-sprite.json`
59319         }
59320
59321         function tag_classes(p) {
59322             var s = '';
59323             for (var i in p.tags) {
59324                 s += ' tag-' + i;
59325                 if (p.tags[i] !== '*') {
59326                     s += ' tag-' + i + '-' + p.tags[i];
59327                 }
59328             }
59329             return s;
59330         }
59331
59332         var fill = selection$$1.selectAll('.preset-icon-fill')
59333             .data([0]);
59334
59335         fill = fill.enter()
59336             .append('div')
59337             .merge(fill);
59338
59339         fill
59340             .attr('class', function() {
59341                 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
59342             });
59343
59344         var frame = selection$$1.selectAll('.preset-icon-frame')
59345             .data([0]);
59346
59347         frame = frame.enter()
59348             .append('div')
59349             .call(svgIcon('#preset-icon-frame'))
59350             .merge(frame);
59351
59352         frame
59353             .attr('class', function() {
59354                 return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
59355             });
59356
59357
59358         var icon = selection$$1.selectAll('.preset-icon')
59359             .data([0]);
59360
59361         icon = icon.enter()
59362             .append('div')
59363             .attr('class', 'preset-icon')
59364             .call(svgIcon(''))
59365             .merge(icon);
59366
59367         icon
59368             .attr('class', 'preset-icon preset-icon-' + (isMaki ? '32' : (geom === 'area' ? '44' : '60')));
59369
59370         icon.selectAll('svg')
59371             .attr('class', function() {
59372                 return 'icon ' + picon + tag_classes(p);
59373             });
59374
59375         icon.selectAll('use')       // workaround: maki parking-24 broken?
59376             .attr('href', '#' + picon + (isMaki ? (picon === 'parking' ? '-18' : '-24') : ''));
59377     }
59378
59379
59380     presetIcon.preset = function(_) {
59381         if (!arguments.length) return preset;
59382         preset = utilFunctor(_);
59383         return presetIcon;
59384     };
59385
59386
59387     presetIcon.geometry = function(_) {
59388         if (!arguments.length) return geometry;
59389         geometry = utilFunctor(_);
59390         return presetIcon;
59391     };
59392
59393     return presetIcon;
59394 }
59395
59396 function d3combobox() {
59397     var event$$1 = dispatch('accept'),
59398         data = [],
59399         suggestions = [],
59400         minItems = 2,
59401         caseSensitive = false;
59402
59403     var fetcher = function(val, cb) {
59404         cb(data.filter(function(d) {
59405             return d.value
59406                 .toString()
59407                 .toLowerCase()
59408                 .indexOf(val.toLowerCase()) !== -1;
59409         }));
59410     };
59411
59412     var combobox = function(input, attachTo) {
59413         var idx = -1,
59414             container = select(document.body)
59415                 .selectAll('div.combobox')
59416                 .filter(function(d) { return d === input.node(); }),
59417             shown = !container.empty();
59418
59419         input
59420             .classed('combobox-input', true)
59421             .on('focus.typeahead', focus)
59422             .on('blur.typeahead', blur)
59423             .on('keydown.typeahead', keydown)
59424             .on('keyup.typeahead', keyup)
59425             .on('input.typeahead', change)
59426             .each(function() {
59427                 var parent = this.parentNode,
59428                     sibling = this.nextSibling;
59429
59430                 var caret = select(parent).selectAll('.combobox-caret')
59431                     .filter(function(d) { return d === input.node(); })
59432                     .data([input.node()]);
59433
59434                 caret = caret.enter()
59435                   .insert('div', function() { return sibling; })
59436                     .attr('class', 'combobox-caret')
59437                   .merge(caret);
59438
59439                 caret
59440                     .on('mousedown', function () {
59441                         // prevent the form element from blurring. it blurs
59442                         // on mousedown
59443                         event.stopPropagation();
59444                         event.preventDefault();
59445                         if (!shown) {
59446                             input.node().focus();
59447                             fetch('', render);
59448                         } else {
59449                             hide();
59450                         }
59451                     });
59452             });
59453
59454         function focus() {
59455             fetch(value(), render);
59456         }
59457
59458         function blur() {
59459             window.setTimeout(hide, 150);
59460         }
59461
59462         function show() {
59463             if (!shown) {
59464                 container = select(document.body)
59465                     .insert('div', ':first-child')
59466                     .datum(input.node())
59467                     .attr('class', 'combobox')
59468                     .style('position', 'absolute')
59469                     .style('display', 'block')
59470                     .style('left', '0px')
59471                     .on('mousedown', function () {
59472                         // prevent moving focus out of the text field
59473                         event.preventDefault();
59474                     });
59475
59476                 select(document.body)
59477                     .on('scroll.combobox', render, true);
59478
59479                 shown = true;
59480             }
59481         }
59482
59483         function hide() {
59484             if (shown) {
59485                 idx = -1;
59486                 container.remove();
59487
59488                 select(document.body)
59489                     .on('scroll.combobox', null);
59490
59491                 shown = false;
59492             }
59493         }
59494
59495         function keydown() {
59496            switch (event.keyCode) {
59497                // backspace, delete
59498                case 8:
59499                case 46:
59500                    input.on('input.typeahead', function() {
59501                        idx = -1;
59502                        render();
59503                        var start = input.property('selectionStart');
59504                        input.node().setSelectionRange(start, start);
59505                        input.on('input.typeahead', change);
59506                    });
59507                    break;
59508                // tab
59509                case 9:
59510                    container.selectAll('a.selected').each(function (d) {
59511                        event$$1.call('accept', this, d);
59512                    });
59513                    hide();
59514                    break;
59515                // return
59516                case 13:
59517                    event.preventDefault();
59518                    break;
59519                // up arrow
59520                case 38:
59521                    nav(-1);
59522                    event.preventDefault();
59523                    break;
59524                // down arrow
59525                case 40:
59526                    nav(+1);
59527                    event.preventDefault();
59528                    break;
59529            }
59530            event.stopPropagation();
59531         }
59532
59533         function keyup() {
59534             switch (event.keyCode) {
59535                 // escape
59536                 case 27:
59537                     hide();
59538                     break;
59539                 // return
59540                 case 13:
59541                     container.selectAll('a.selected').each(function (d) {
59542                        event$$1.call('accept', this, d);
59543                     });
59544                     hide();
59545                     break;
59546             }
59547         }
59548
59549         function change() {
59550             fetch(value(), function() {
59551                 if (input.property('selectionEnd') === input.property('value').length) {
59552                     autocomplete();
59553                 }
59554                 render();
59555             });
59556         }
59557
59558         function nav(dir) {
59559             if (!suggestions.length) return;
59560             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
59561             input.property('value', suggestions[idx].value);
59562             render();
59563             ensureVisible();
59564         }
59565
59566         function value() {
59567             var value = input.property('value'),
59568                 start = input.property('selectionStart'),
59569                 end = input.property('selectionEnd');
59570
59571             if (start && end) {
59572                 value = value.substring(0, start);
59573             }
59574
59575             return value;
59576         }
59577
59578         function fetch(v, cb) {
59579             fetcher.call(input, v, function(_) {
59580                 suggestions = _;
59581                 cb();
59582             });
59583         }
59584
59585         function autocomplete() {
59586             var v = caseSensitive ? value() : value().toLowerCase();
59587             idx = -1;
59588             if (!v) return;
59589
59590             for (var i = 0; i < suggestions.length; i++) {
59591                 var suggestion = suggestions[i].value,
59592                     compare = caseSensitive ? suggestion : suggestion.toLowerCase();
59593
59594                 if (compare.indexOf(v) === 0) {
59595                     idx = i;
59596                     input.property('value', suggestion);
59597                     input.node().setSelectionRange(v.length, suggestion.length);
59598                     return;
59599                 }
59600             }
59601         }
59602
59603         function render() {
59604             if (suggestions.length >= minItems && document.activeElement === input.node()) {
59605                 show();
59606             } else {
59607                 hide();
59608                 return;
59609             }
59610
59611             var options = container
59612                 .selectAll('a.combobox-option')
59613                 .data(suggestions, function(d) { return d.value; });
59614
59615             options.exit()
59616                 .remove();
59617
59618             options.enter()
59619                 .append('a')
59620                 .attr('class', 'combobox-option')
59621                 .text(function(d) { return d.value; })
59622                 .merge(options)
59623                 .attr('title', function(d) { return d.title; })
59624                 .classed('selected', function(d, i) { return i === idx; })
59625                 .on('mouseover', select$$1)
59626                 .on('click', accept)
59627                 .order();
59628
59629
59630             var node = attachTo ? attachTo.node() : input.node(),
59631                 rect = node.getBoundingClientRect();
59632
59633             container
59634                 .style('left', rect.left + 'px')
59635                 .style('width', rect.width + 'px')
59636                 .style('top', rect.height + rect.top + 'px');
59637         }
59638
59639         function select$$1(d, i) {
59640             idx = i;
59641             render();
59642         }
59643
59644         function ensureVisible() {
59645             var node = container.selectAll('a.selected').node();
59646             if (node) node.scrollIntoView();
59647         }
59648
59649         function accept(d) {
59650             if (!shown) return;
59651             input
59652                 .property('value', d.value)
59653                 .dispatch('change');
59654             event$$1.call('accept', this, d);
59655             hide();
59656         }
59657     };
59658
59659     combobox.fetcher = function(_) {
59660         if (!arguments.length) return fetcher;
59661         fetcher = _;
59662         return combobox;
59663     };
59664
59665     combobox.data = function(_) {
59666         if (!arguments.length) return data;
59667         data = _;
59668         return combobox;
59669     };
59670
59671     combobox.minItems = function(_) {
59672         if (!arguments.length) return minItems;
59673         minItems = _;
59674         return combobox;
59675     };
59676
59677     combobox.caseSensitive = function(_) {
59678         if (!arguments.length) return caseSensitive;
59679         caseSensitive = _;
59680         return combobox;
59681     };
59682
59683     return utilRebind(combobox, event$$1, 'on');
59684 }
59685
59686
59687 d3combobox.off = function(input) {
59688     input
59689         .on('focus.typeahead', null)
59690         .on('blur.typeahead', null)
59691         .on('keydown.typeahead', null)
59692         .on('keyup.typeahead', null)
59693         .on('input.typeahead', null)
59694         .each(function() {
59695             select(this.parentNode).selectAll('.combobox-caret')
59696                 .filter(function(d) { return d === input.node(); })
59697                 .on('mousedown', null);
59698         });
59699
59700     select(document.body)
59701         .on('scroll.combobox', null);
59702 };
59703
59704 function uiDisclosure() {
59705     var dispatch$$1 = dispatch('toggled'),
59706         title,
59707         expanded = false,
59708         content = function () {};
59709
59710
59711     var disclosure = function(selection$$1) {
59712         var hideToggle = selection$$1.selectAll('.hide-toggle')
59713             .data([0]);
59714
59715         hideToggle = hideToggle.enter()
59716             .append('a')
59717             .attr('href', '#')
59718             .attr('class', 'hide-toggle')
59719             .merge(hideToggle);
59720
59721         hideToggle
59722             .text(title)
59723             .on('click', toggle)
59724             .classed('expanded', expanded);
59725
59726
59727         var wrap = selection$$1.selectAll('div')
59728             .data([0]);
59729
59730         wrap = wrap.enter()
59731             .append('div')
59732             .merge(wrap);
59733
59734         wrap
59735             .classed('hide', !expanded)
59736             .call(content);
59737
59738
59739         function toggle() {
59740             expanded = !expanded;
59741             hideToggle.classed('expanded', expanded);
59742             wrap.call(uiToggle(expanded));
59743             dispatch$$1.call('toggled', this, expanded);
59744         }
59745     };
59746
59747
59748     disclosure.title = function(_) {
59749         if (!arguments.length) return title;
59750         title = _;
59751         return disclosure;
59752     };
59753
59754
59755     disclosure.expanded = function(_) {
59756         if (!arguments.length) return expanded;
59757         expanded = _;
59758         return disclosure;
59759     };
59760
59761
59762     disclosure.content = function(_) {
59763         if (!arguments.length) return content;
59764         content = _;
59765         return disclosure;
59766     };
59767
59768
59769     return utilRebind(disclosure, dispatch$$1, 'on');
59770 }
59771
59772 function uiRawMemberEditor(context) {
59773     var id,
59774         taginfo = services.taginfo;
59775
59776
59777     function selectMember(d) {
59778         event.preventDefault();
59779         context.enter(modeSelect(context, [d.id]));
59780     }
59781
59782
59783     function changeRole(d) {
59784         var role = select(this).property('value');
59785         var member = { id: d.id, type: d.type, role: role };
59786         context.perform(
59787             actionChangeMember(d.relation.id, member, d.index),
59788             t('operations.change_role.annotation')
59789         );
59790     }
59791
59792
59793     function deleteMember(d) {
59794         context.perform(
59795             actionDeleteMember(d.relation.id, d.index),
59796             t('operations.delete_member.annotation')
59797         );
59798
59799         if (!context.hasEntity(d.relation.id)) {
59800             context.enter(modeBrowse$$1(context));
59801         }
59802     }
59803
59804
59805     function rawMemberEditor(selection$$1) {
59806         var entity = context.entity(id),
59807             memberships = [];
59808
59809         entity.members.forEach(function(member, index) {
59810             memberships.push({
59811                 index: index,
59812                 id: member.id,
59813                 type: member.type,
59814                 role: member.role,
59815                 relation: entity,
59816                 member: context.hasEntity(member.id)
59817             });
59818         });
59819
59820         selection$$1.call(uiDisclosure()
59821             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
59822             .expanded(true)
59823             .on('toggled', toggled)
59824             .content(content)
59825         );
59826
59827
59828         function toggled(expanded) {
59829             if (expanded) {
59830                 selection$$1.node().parentNode.scrollTop += 200;
59831             }
59832         }
59833
59834
59835         function content(wrap) {
59836             var list = wrap.selectAll('.member-list')
59837                 .data([0]);
59838
59839             list = list.enter()
59840                 .append('ul')
59841                 .attr('class', 'member-list')
59842                 .merge(list);
59843
59844
59845             var items = list.selectAll('li')
59846                 .data(memberships, function(d) {
59847                     return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
59848                         (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
59849                 });
59850
59851             items.exit()
59852                 .each(unbind)
59853                 .remove();
59854
59855             var enter = items.enter()
59856                 .append('li')
59857                 .attr('class', 'member-row form-field')
59858                 .classed('member-incomplete', function(d) { return !d.member; });
59859
59860             enter
59861                 .each(function(d) {
59862                     if (d.member) {
59863                         var label = select(this).append('label')
59864                             .attr('class', 'form-label')
59865                             .append('a')
59866                             .attr('href', '#')
59867                             .on('click', selectMember);
59868
59869                         label.append('span')
59870                             .attr('class', 'member-entity-type')
59871                             .text(function(d) {
59872                                 var matched = context.presets().match(d.member, context.graph());
59873                                 return (matched && matched.name()) || utilDisplayType(d.member.id);
59874                             });
59875
59876                         label.append('span')
59877                             .attr('class', 'member-entity-name')
59878                             .text(function(d) { return utilDisplayName(d.member); });
59879
59880                     } else {
59881                         select(this).append('label')
59882                             .attr('class', 'form-label')
59883                             .text(t('inspector.incomplete', { id: d.id }));
59884                     }
59885                 });
59886
59887             enter
59888                 .append('input')
59889                 .attr('class', 'member-role')
59890                 .property('type', 'text')
59891                 .attr('maxlength', 255)
59892                 .attr('placeholder', t('inspector.role'))
59893                 .property('value', function(d) { return d.role; })
59894                 .on('change', changeRole);
59895
59896             enter
59897                 .append('button')
59898                 .attr('tabindex', -1)
59899                 .attr('class', 'remove button-input-action member-delete minor')
59900                 .on('click', deleteMember)
59901                 .call(svgIcon('#operation-delete'));
59902
59903             if (taginfo) {
59904                 enter.each(bindTypeahead);
59905             }
59906
59907
59908             function bindTypeahead(d) {
59909                 var row = select(this),
59910                     role = row.selectAll('input.member-role');
59911
59912                 function sort(value, data) {
59913                     var sameletter = [],
59914                         other = [];
59915                     for (var i = 0; i < data.length; i++) {
59916                         if (data[i].value.substring(0, value.length) === value) {
59917                             sameletter.push(data[i]);
59918                         } else {
59919                             other.push(data[i]);
59920                         }
59921                     }
59922                     return sameletter.concat(other);
59923                 }
59924
59925                 role.call(d3combobox()
59926                     .fetcher(function(role, callback) {
59927                         var rtype = entity.tags.type;
59928                         taginfo.roles({
59929                             debounce: true,
59930                             rtype: rtype || '',
59931                             geometry: context.geometry(d.member.id),
59932                             query: role
59933                         }, function(err, data) {
59934                             if (!err) callback(sort(role, data));
59935                         });
59936                     }));
59937             }
59938
59939
59940             function unbind() {
59941                 var row = select(this);
59942
59943                 row.selectAll('input.member-role')
59944                     .call(d3combobox.off);
59945             }
59946         }
59947     }
59948
59949
59950     rawMemberEditor.entityID = function(_) {
59951         if (!arguments.length) return id;
59952         id = _;
59953         return rawMemberEditor;
59954     };
59955
59956
59957     return rawMemberEditor;
59958 }
59959
59960 function uiRawMembershipEditor(context) {
59961     var taginfo = services.taginfo,
59962         id, showBlank;
59963
59964
59965     function selectRelation(d) {
59966         event.preventDefault();
59967         context.enter(modeSelect(context, [d.relation.id]));
59968     }
59969
59970
59971     function changeRole(d) {
59972         var role = select(this).property('value');
59973         context.perform(
59974             actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
59975             t('operations.change_role.annotation')
59976         );
59977     }
59978
59979
59980     function addMembership(d, role) {
59981         showBlank = false;
59982
59983         if (d.relation) {
59984             context.perform(
59985                 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
59986                 t('operations.add_member.annotation')
59987             );
59988
59989         } else {
59990             var relation = osmRelation();
59991             context.perform(
59992                 actionAddEntity(relation),
59993                 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
59994                 t('operations.add.annotation.relation')
59995             );
59996
59997             context.enter(modeSelect(context, [relation.id]));
59998         }
59999     }
60000
60001
60002     function deleteMembership(d) {
60003         context.perform(
60004             actionDeleteMember(d.relation.id, d.index),
60005             t('operations.delete_member.annotation')
60006         );
60007     }
60008
60009
60010     function relations(q) {
60011         var newRelation = {
60012                 relation: null,
60013                 value: t('inspector.new_relation')
60014             },
60015             result = [],
60016             graph = context.graph();
60017
60018         context.intersects(context.extent()).forEach(function(entity) {
60019             if (entity.type !== 'relation' || entity.id === id)
60020                 return;
60021
60022             var matched = context.presets().match(entity, graph),
60023                 presetName = (matched && matched.name()) || t('inspector.relation'),
60024                 entityName = utilDisplayName(entity) || '';
60025
60026             var value = presetName + ' ' + entityName;
60027             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
60028                 return;
60029
60030             result.push({
60031                 relation: entity,
60032                 value: value
60033             });
60034         });
60035
60036         result.sort(function(a, b) {
60037             return osmRelation.creationOrder(a.relation, b.relation);
60038         });
60039
60040         // Dedupe identical names by appending relation id - see #2891
60041         var dupeGroups = lodash(result)
60042             .groupBy('value')
60043             .filter(function(v) { return v.length > 1; })
60044             .value();
60045
60046         dupeGroups.forEach(function(group) {
60047             group.forEach(function(obj) {
60048                 obj.value += ' ' + obj.relation.id;
60049             });
60050         });
60051
60052         result.unshift(newRelation);
60053         return result;
60054     }
60055
60056
60057     function rawMembershipEditor(selection$$1) {
60058         var entity = context.entity(id),
60059             memberships = [];
60060
60061         context.graph().parentRelations(entity).forEach(function(relation) {
60062             relation.members.forEach(function(member, index) {
60063                 if (member.id === entity.id) {
60064                     memberships.push({ relation: relation, member: member, index: index });
60065                 }
60066             });
60067         });
60068
60069         selection$$1.call(uiDisclosure()
60070             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
60071             .expanded(true)
60072             .on('toggled', toggled)
60073             .content(content)
60074         );
60075
60076
60077         function toggled(expanded) {
60078             if (expanded) {
60079                 selection$$1.node().parentNode.scrollTop += 200;
60080             }
60081         }
60082
60083
60084         function content(wrap) {
60085             var list = wrap.selectAll('.member-list')
60086                 .data([0]);
60087
60088             list = list.enter()
60089                 .append('ul')
60090                 .attr('class', 'member-list')
60091                 .merge(list);
60092
60093
60094             var items = list.selectAll('li.member-row-normal')
60095                 .data(memberships, function(d) {
60096                     return osmEntity$$1.key(d.relation) + ',' + d.index;
60097                 });
60098
60099             items.exit()
60100                 .each(unbind)
60101                 .remove();
60102
60103             var enter = items.enter()
60104                 .append('li')
60105                 .attr('class', 'member-row member-row-normal form-field');
60106
60107             var label = enter
60108                 .append('label')
60109                 .attr('class', 'form-label')
60110                 .append('a')
60111                 .attr('href', '#')
60112                 .on('click', selectRelation);
60113
60114             label
60115                 .append('span')
60116                 .attr('class', 'member-entity-type')
60117                 .text(function(d) {
60118                     var matched = context.presets().match(d.relation, context.graph());
60119                     return (matched && matched.name()) || t('inspector.relation');
60120                 });
60121
60122             label
60123                 .append('span')
60124                 .attr('class', 'member-entity-name')
60125                 .text(function(d) { return utilDisplayName(d.relation); });
60126
60127             enter
60128                 .append('input')
60129                 .attr('class', 'member-role')
60130                 .property('type', 'text')
60131                 .attr('maxlength', 255)
60132                 .attr('placeholder', t('inspector.role'))
60133                 .property('value', function(d) { return d.member.role; })
60134                 .on('change', changeRole);
60135
60136             enter
60137                 .append('button')
60138                 .attr('tabindex', -1)
60139                 .attr('class', 'remove button-input-action member-delete minor')
60140                 .on('click', deleteMembership)
60141                 .call(svgIcon('#operation-delete'));
60142
60143             if (taginfo) {
60144                 enter.each(bindTypeahead);
60145             }
60146
60147
60148             var newrow = list.selectAll('.member-row-new')
60149                 .data(showBlank ? [0] : []);
60150
60151             newrow.exit()
60152                 .remove();
60153
60154             enter = newrow.enter()
60155                 .append('li')
60156                 .attr('class', 'member-row member-row-new form-field');
60157
60158             enter
60159                 .append('input')
60160                 .attr('type', 'text')
60161                 .attr('class', 'member-entity-input');
60162
60163             enter
60164                 .append('input')
60165                 .attr('class', 'member-role')
60166                 .property('type', 'text')
60167                 .attr('maxlength', 255)
60168                 .attr('placeholder', t('inspector.role'))
60169                 .on('change', changeRole);
60170
60171             enter
60172                 .append('button')
60173                 .attr('tabindex', -1)
60174                 .attr('class', 'remove button-input-action member-delete minor')
60175                 .on('click', deleteMembership)
60176                 .call(svgIcon('#operation-delete'));
60177
60178             newrow = newrow
60179                 .merge(enter);
60180
60181             newrow.selectAll('.member-entity-input')
60182                 .call(d3combobox()
60183                     .minItems(1)
60184                     .fetcher(function(value, callback) { callback(relations(value)); })
60185                     .on('accept', onAccept)
60186                 );
60187
60188
60189             var addrel = wrap.selectAll('.add-relation')
60190                 .data([0]);
60191
60192             addrel = addrel.enter()
60193                 .append('button')
60194                 .attr('class', 'add-relation')
60195                 .merge(addrel);
60196
60197             addrel
60198                 .call(svgIcon('#icon-plus', 'light'))
60199                 .on('click', function() {
60200                     showBlank = true;
60201                     content(wrap);
60202                     list.selectAll('.member-entity-input').node().focus();
60203                 });
60204
60205
60206             function onAccept(d) {
60207                 var role = list.selectAll('.member-row-new .member-role').property('value');
60208                 addMembership(d, role);
60209             }
60210
60211
60212             function bindTypeahead(d) {
60213                 var row = select(this),
60214                     role = row.selectAll('input.member-role');
60215
60216                 function sort(value, data) {
60217                     var sameletter = [],
60218                         other = [];
60219                     for (var i = 0; i < data.length; i++) {
60220                         if (data[i].value.substring(0, value.length) === value) {
60221                             sameletter.push(data[i]);
60222                         } else {
60223                             other.push(data[i]);
60224                         }
60225                     }
60226                     return sameletter.concat(other);
60227                 }
60228
60229                 role.call(d3combobox()
60230                     .fetcher(function(role, callback) {
60231                         var rtype = d.relation.tags.type;
60232                         taginfo.roles({
60233                             debounce: true,
60234                             rtype: rtype || '',
60235                             geometry: context.geometry(id),
60236                             query: role
60237                         }, function(err, data) {
60238                             if (!err) callback(sort(role, data));
60239                         });
60240                     }));
60241             }
60242
60243
60244             function unbind() {
60245                 var row = select(this);
60246
60247                 row.selectAll('input.member-role')
60248                     .call(d3combobox.off);
60249             }
60250         }
60251     }
60252
60253
60254     rawMembershipEditor.entityID = function(_) {
60255         if (!arguments.length) return id;
60256         id = _;
60257         return rawMembershipEditor;
60258     };
60259
60260
60261     return rawMembershipEditor;
60262 }
60263
60264 function uiTagReference(tag) {
60265     var taginfo = services.taginfo,
60266         tagReference = {},
60267         button,
60268         body,
60269         loaded,
60270         showing;
60271
60272
60273     function findLocal(data) {
60274         var locale = utilDetect().locale.toLowerCase(),
60275             localized;
60276
60277         localized = lodash.find(data, function(d) {
60278             return d.lang.toLowerCase() === locale;
60279         });
60280         if (localized) return localized;
60281
60282         // try the non-regional version of a language, like
60283         // 'en' if the language is 'en-US'
60284         if (locale.indexOf('-') !== -1) {
60285             var first = locale.split('-')[0];
60286             localized = lodash.find(data, function(d) {
60287                 return d.lang.toLowerCase() === first;
60288             });
60289             if (localized) return localized;
60290         }
60291
60292         // finally fall back to english
60293         return lodash.find(data, function(d) {
60294             return d.lang.toLowerCase() === 'en';
60295         });
60296     }
60297
60298
60299     function load(param) {
60300         if (!taginfo) return;
60301
60302         button.classed('tag-reference-loading', true);
60303
60304         taginfo.docs(param, function show(err, data) {
60305             var docs;
60306             if (!err && data) {
60307                 docs = findLocal(data);
60308             }
60309
60310             body.html('');
60311
60312
60313             if (!docs || !docs.title) {
60314                 if (param.hasOwnProperty('value')) {
60315                     load(lodash.omit(param, 'value'));   // retry with key only
60316                 } else {
60317                     body.append('p').text(t('inspector.no_documentation_key'));
60318                     done();
60319                 }
60320                 return;
60321             }
60322
60323
60324             if (docs.image && docs.image.thumb_url_prefix) {
60325                 body
60326                     .append('img')
60327                     .attr('class', 'wiki-image')
60328                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
60329                     .on('load', function() { done(); })
60330                     .on('error', function() { select(this).remove(); done(); });
60331             } else {
60332                 done();
60333             }
60334
60335             body
60336                 .append('p')
60337                 .text(docs.description || t('inspector.documentation_redirect'));
60338
60339             body
60340                 .append('a')
60341                 .attr('target', '_blank')
60342                 .attr('tabindex', -1)
60343                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
60344                 .call(svgIcon('#icon-out-link', 'inline'))
60345                 .append('span')
60346                 .text(t('inspector.reference'));
60347         });
60348     }
60349
60350
60351     function done() {
60352         loaded = true;
60353
60354         button.classed('tag-reference-loading', false);
60355
60356         body.transition()
60357             .duration(200)
60358             .style('max-height', '200px')
60359             .style('opacity', '1');
60360
60361         showing = true;
60362     }
60363
60364
60365     function hide(selection$$1) {
60366         selection$$1 = selection$$1 || body.transition().duration(200);
60367
60368         selection$$1
60369             .style('max-height', '0px')
60370             .style('opacity', '0');
60371
60372         showing = false;
60373     }
60374
60375
60376     tagReference.button = function(selection$$1) {
60377         button = selection$$1.selectAll('.tag-reference-button')
60378             .data([0]);
60379
60380         button = button.enter()
60381             .append('button')
60382             .attr('class', 'tag-reference-button')
60383             .attr('tabindex', -1)
60384             .call(svgIcon('#icon-inspect'))
60385             .merge(button);
60386
60387         button
60388             .on('click', function () {
60389                 event.stopPropagation();
60390                 event.preventDefault();
60391                 if (showing) {
60392                     hide();
60393                 } else if (loaded) {
60394                     done();
60395                 } else {
60396                     load(tag);
60397                 }
60398             });
60399     };
60400
60401
60402     tagReference.body = function(selection$$1) {
60403         body = selection$$1.selectAll('.tag-reference-body')
60404             .data([0]);
60405
60406         body = body.enter()
60407             .append('div')
60408             .attr('class', 'tag-reference-body cf')
60409             .style('max-height', '0')
60410             .style('opacity', '0')
60411             .merge(body);
60412
60413         if (showing === false) {
60414             hide(body);
60415         }
60416     };
60417
60418
60419     tagReference.showing = function(_) {
60420         if (!arguments.length) return showing;
60421         showing = _;
60422         return tagReference;
60423     };
60424
60425
60426     return tagReference;
60427 }
60428
60429 function uiRawTagEditor(context) {
60430     var taginfo = services.taginfo,
60431         dispatch$$1 = dispatch('change'),
60432         showBlank = false,
60433         state,
60434         preset,
60435         tags,
60436         id;
60437
60438
60439     function rawTagEditor(selection$$1) {
60440         var count = Object.keys(tags).filter(function(d) { return d; }).length;
60441
60442         selection$$1.call(uiDisclosure()
60443             .title(t('inspector.all_tags') + ' (' + count + ')')
60444             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
60445             .on('toggled', toggled)
60446             .content(content));
60447
60448         function toggled(expanded) {
60449             context.storage('raw_tag_editor.expanded', expanded);
60450             if (expanded) {
60451                 selection$$1.node().parentNode.scrollTop += 200;
60452             }
60453         }
60454     }
60455
60456
60457     function content(wrap) {
60458         var entries$$1 = entries(tags);
60459
60460         if (!entries$$1.length || showBlank) {
60461             showBlank = false;
60462             entries$$1.push({key: '', value: ''});
60463         }
60464
60465         var list = wrap.selectAll('.tag-list')
60466             .data([0]);
60467
60468         list = list.enter()
60469             .append('ul')
60470             .attr('class', 'tag-list')
60471             .merge(list);
60472
60473         var newTag = wrap.selectAll('.add-tag')
60474             .data([0]);
60475
60476         newTag.enter()
60477             .append('button')
60478             .attr('class', 'add-tag')
60479             .on('click', addTag)
60480             .call(svgIcon('#icon-plus', 'light'));
60481
60482
60483         var items = list.selectAll('.tag-row')
60484             .data(entries$$1, function(d) { return d.key; });
60485
60486         items.exit()
60487             .each(unbind)
60488             .remove();
60489
60490         // Enter
60491
60492         var enter = items.enter()
60493             .append('li')
60494             .attr('class', 'tag-row cf');
60495
60496         enter
60497             .append('div')
60498             .attr('class', 'key-wrap')
60499             .append('input')
60500             .property('type', 'text')
60501             .attr('class', 'key')
60502             .attr('maxlength', 255)
60503             .on('blur', keyChange)
60504             .on('change', keyChange);
60505
60506         enter
60507             .append('div')
60508             .attr('class', 'input-wrap-position')
60509             .append('input')
60510             .property('type', 'text')
60511             .attr('class', 'value')
60512             .attr('maxlength', 255)
60513             .on('blur', valueChange)
60514             .on('change', valueChange)
60515             .on('keydown.push-more', pushMore);
60516
60517         enter
60518             .append('button')
60519             .attr('tabindex', -1)
60520             .attr('class', 'remove minor')
60521             .call(svgIcon('#operation-delete'));
60522
60523
60524         // Update
60525
60526         items = items
60527             .merge(enter)
60528             .sort(function(a, b) {
60529                 return (a.key === '') ? 1
60530                     : (b.key === '') ? -1
60531                     : ascending(a.key, b.key);
60532             });
60533
60534         items
60535             .each(function(tag) {
60536                 var row = select(this),
60537                     key = row.select('input.key'),      // propagate bound data to child
60538                     value = row.select('input.value');  // propagate bound data to child
60539
60540                 if (taginfo) {
60541                     bindTypeahead(key, value);
60542                 }
60543
60544                 var isRelation = (context.entity(id).type === 'relation'),
60545                     reference;
60546
60547                 if (isRelation && tag.key === 'type') {
60548                     reference = uiTagReference({ rtype: tag.value }, context);
60549                 } else {
60550                     reference = uiTagReference({ key: tag.key, value: tag.value }, context);
60551                 }
60552
60553                 if (state === 'hover') {
60554                     reference.showing(false);
60555                 }
60556
60557                 row
60558                     .call(reference.button)
60559                     .call(reference.body);
60560             });
60561
60562         items.selectAll('input.key')
60563             .attr('title', function(d) { return d.key; })
60564             .call(utilGetSetValue, function(d) { return d.key; });
60565
60566         items.selectAll('input.value')
60567             .attr('title', function(d) { return d.value; })
60568             .call(utilGetSetValue, function(d) { return d.value; });
60569
60570         items.selectAll('button.remove')
60571             .on('click', removeTag);
60572
60573
60574         function pushMore() {
60575             if (event.keyCode === 9 && !event.shiftKey &&
60576                 list.selectAll('li:last-child input.value').node() === this) {
60577                 addTag();
60578             }
60579         }
60580
60581
60582         function bindTypeahead(key, value) {
60583
60584             function sort(value, data) {
60585                 var sameletter = [],
60586                     other = [];
60587                 for (var i = 0; i < data.length; i++) {
60588                     if (data[i].value.substring(0, value.length) === value) {
60589                         sameletter.push(data[i]);
60590                     } else {
60591                         other.push(data[i]);
60592                     }
60593                 }
60594                 return sameletter.concat(other);
60595             }
60596
60597             key.call(d3combobox()
60598                 .fetcher(function(value, callback) {
60599                     taginfo.keys({
60600                         debounce: true,
60601                         geometry: context.geometry(id),
60602                         query: value
60603                     }, function(err, data) {
60604                         if (!err) callback(sort(value, data));
60605                     });
60606                 }));
60607
60608             value.call(d3combobox()
60609                 .fetcher(function(value, callback) {
60610                     taginfo.values({
60611                         debounce: true,
60612                         key: utilGetSetValue(key),
60613                         geometry: context.geometry(id),
60614                         query: value
60615                     }, function(err, data) {
60616                         if (!err) callback(sort(value, data));
60617                     });
60618                 }));
60619         }
60620
60621
60622         function unbind() {
60623             var row = select(this);
60624
60625             row.selectAll('input.key')
60626                 .call(d3combobox.off);
60627
60628             row.selectAll('input.value')
60629                 .call(d3combobox.off);
60630         }
60631
60632
60633         function keyChange(d) {
60634             var kOld = d.key,
60635                 kNew = this.value.trim(),
60636                 tag = {};
60637
60638             if (kNew && kNew !== kOld) {
60639                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
60640                     base = match[1],
60641                     suffix = +(match[2] || 1);
60642                 while (tags[kNew]) {  // rename key if already in use
60643                     kNew = base + '_' + suffix++;
60644                 }
60645             }
60646             tag[kOld] = undefined;
60647             tag[kNew] = d.value;
60648             d.key = kNew; // Maintain DOM identity through the subsequent update.
60649             this.value = kNew;
60650             dispatch$$1.call('change', this, tag);
60651         }
60652
60653
60654         function valueChange(d) {
60655             var tag = {};
60656             tag[d.key] = this.value;
60657             dispatch$$1.call('change', this, tag);
60658         }
60659
60660
60661         function removeTag(d) {
60662             var tag = {};
60663             tag[d.key] = undefined;
60664             dispatch$$1.call('change', this, tag);
60665             select(this.parentNode).remove();
60666         }
60667
60668
60669         function addTag() {
60670             // Wrapped in a setTimeout in case it's being called from a blur
60671             // handler. Without the setTimeout, the call to `content` would
60672             // wipe out the pending value change.
60673             setTimeout(function() {
60674                 showBlank = true;
60675                 content(wrap);
60676                 list.selectAll('li:last-child input.key').node().focus();
60677             }, 0);
60678         }
60679     }
60680
60681
60682     rawTagEditor.state = function(_) {
60683         if (!arguments.length) return state;
60684         state = _;
60685         return rawTagEditor;
60686     };
60687
60688
60689     rawTagEditor.preset = function(_) {
60690         if (!arguments.length) return preset;
60691         preset = _;
60692         return rawTagEditor;
60693     };
60694
60695
60696     rawTagEditor.tags = function(_) {
60697         if (!arguments.length) return tags;
60698         tags = _;
60699         return rawTagEditor;
60700     };
60701
60702
60703     rawTagEditor.entityID = function(_) {
60704         if (!arguments.length) return id;
60705         id = _;
60706         return rawTagEditor;
60707     };
60708
60709
60710     return utilRebind(rawTagEditor, dispatch$$1, 'on');
60711 }
60712
60713 function uiFieldCheck(field) {
60714     var dispatch$$1 = dispatch('change'),
60715         options = field.strings && field.strings.options,
60716         values$$1 = [],
60717         texts = [],
60718         input = select(null),
60719         text$$1 = select(null),
60720         label = select(null),
60721         entity, value;
60722
60723     if (options) {
60724         for (var k in options) {
60725             values$$1.push(k === 'undefined' ? undefined : k);
60726             texts.push(field.t('options.' + k, { 'default': options[k] }));
60727         }
60728     } else {
60729         values$$1 = [undefined, 'yes'];
60730         texts = [t('inspector.unknown'), t('inspector.check.yes')];
60731         if (field.type === 'check') {
60732             values$$1.push('no');
60733             texts.push(t('inspector.check.no'));
60734         }
60735     }
60736
60737
60738     var check = function(selection$$1) {
60739         // hack: pretend oneway field is a oneway_yes field
60740         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
60741         if (field.id === 'oneway') {
60742             for (var key in entity.tags) {
60743                 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
60744                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
60745                     break;
60746                 }
60747             }
60748         }
60749
60750         selection$$1.classed('checkselect', 'true');
60751
60752         label = selection$$1.selectAll('.preset-input-wrap')
60753             .data([0]);
60754
60755         var enter = label.enter()
60756             .append('label')
60757             .attr('class', 'preset-input-wrap');
60758
60759         enter
60760             .append('input')
60761             .property('indeterminate', field.type === 'check')
60762             .attr('type', 'checkbox')
60763             .attr('id', 'preset-input-' + field.id);
60764
60765         enter
60766             .append('span')
60767             .text(texts[0])
60768             .attr('class', 'value');
60769
60770         label = label.merge(enter);
60771         input = label.selectAll('input');
60772         text$$1 = label.selectAll('span.value');
60773
60774         input
60775             .on('click', function() {
60776                 var t$$1 = {};
60777                 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
60778                 dispatch$$1.call('change', this, t$$1);
60779                 event.stopPropagation();
60780             });
60781     };
60782
60783
60784     check.entity = function(_) {
60785         if (!arguments.length) return entity;
60786         entity = _;
60787         return check;
60788     };
60789
60790
60791     check.tags = function(tags) {
60792         value = tags[field.key];
60793         input.property('indeterminate', field.type === 'check' && !value);
60794         input.property('checked', value === 'yes');
60795         text$$1.text(texts[values$$1.indexOf(value)]);
60796         label.classed('set', !!value);
60797     };
60798
60799
60800     check.focus = function() {
60801         input.node().focus();
60802     };
60803
60804     return utilRebind(check, dispatch$$1, 'on');
60805 }
60806
60807 function uiFieldCombo(field, context) {
60808     var dispatch$$1 = dispatch('change'),
60809         nominatim = services.nominatim,
60810         taginfo = services.taginfo,
60811         isMulti = (field.type === 'multiCombo'),
60812         isNetwork = (field.type === 'networkCombo'),
60813         optstrings = field.strings && field.strings.options,
60814         optarray = field.options,
60815         snake_case = (field.snake_case || (field.snake_case === undefined)),
60816         combobox = d3combobox().minItems(isMulti ? 1 : 2),
60817         comboData = [],
60818         multiData = [],
60819         container,
60820         input,
60821         entity,
60822         country;
60823
60824     // ensure multiCombo field.key ends with a ':'
60825     if (isMulti && field.key.match(/:$/) === null) {
60826         field.key += ':';
60827     }
60828
60829
60830     function snake(s) {
60831         return s.replace(/\s+/g, '_');
60832     }
60833
60834     function unsnake(s) {
60835         return s.replace(/_+/g, ' ');
60836     }
60837
60838     function clean(s) {
60839         return s.split(';')
60840             .map(function(s) { return s.trim(); })
60841             .join(';');
60842     }
60843
60844
60845     // returns the tag value for a display value
60846     // (for multiCombo, dval should be the key suffix, not the entire key)
60847     function tagValue(dval) {
60848         dval = clean(dval || '');
60849
60850         if (optstrings) {
60851             var match = lodash.find(comboData, function(o) {
60852                 return o.key && clean(o.value) === dval;
60853             });
60854             if (match) {
60855                 return match.key;
60856             }
60857         }
60858
60859         if (field.type === 'typeCombo' && !dval) {
60860             return 'yes';
60861         }
60862
60863         return (snake_case ? snake(dval) : dval) || undefined;
60864     }
60865
60866
60867     // returns the display value for a tag value
60868     // (for multiCombo, tval should be the key suffix, not the entire key)
60869     function displayValue(tval) {
60870         tval = tval || '';
60871
60872         if (optstrings) {
60873             var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
60874             if (match) {
60875                 return match.value;
60876             }
60877         }
60878
60879         if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
60880             return '';
60881         }
60882
60883         return snake_case ? unsnake(tval) : tval;
60884     }
60885
60886
60887     function objectDifference(a, b) {
60888         return lodash.reject(a, function(d1) {
60889             return lodash.some(b, function(d2) { return d1.value === d2.value; });
60890         });
60891     }
60892
60893
60894     function initCombo(selection$$1, attachTo) {
60895         if (optstrings) {
60896             selection$$1.attr('readonly', 'readonly');
60897             selection$$1.call(combobox, attachTo);
60898             setStaticValues(setPlaceholder);
60899
60900         } else if (optarray) {
60901             selection$$1.call(combobox, attachTo);
60902             setStaticValues(setPlaceholder);
60903
60904         } else if (taginfo) {
60905             selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
60906             setTaginfoValues('', setPlaceholder);
60907         }
60908     }
60909
60910
60911     function setStaticValues(callback) {
60912         if (!(optstrings || optarray)) return;
60913
60914         if (optstrings) {
60915             comboData = Object.keys(optstrings).map(function(k) {
60916                 var v = field.t('options.' + k, { 'default': optstrings[k] });
60917                 return {
60918                     key: k,
60919                     value: v,
60920                     title: v
60921                 };
60922             });
60923
60924         } else if (optarray) {
60925             comboData = optarray.map(function(k) {
60926                 var v = snake_case ? unsnake(k) : k;
60927                 return {
60928                     key: k,
60929                     value: v,
60930                     title: v
60931                 };
60932             });
60933         }
60934
60935         combobox.data(objectDifference(comboData, multiData));
60936         if (callback) callback(comboData);
60937     }
60938
60939
60940     function setTaginfoValues(q, callback) {
60941         var fn = isMulti ? 'multikeys' : 'values';
60942         var query = (isMulti ? field.key : '') + q;
60943         var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
60944         if (hasCountryPrefix) {
60945             query = country + ':';
60946         }
60947         taginfo[fn]({
60948             debounce: true,
60949             key: field.key,
60950             geometry: context.geometry(entity.id),
60951             query: query
60952         }, function(err, data) {
60953             if (err) return;
60954             if (hasCountryPrefix) {
60955                 data = lodash.filter(data, function(d) {
60956                     return d.value.toLowerCase().indexOf(country + ':') === 0;
60957                 });
60958             }
60959             comboData = lodash.map(data, function(d) {
60960                 var k = d.value;
60961                 if (isMulti) k = k.replace(field.key, '');
60962                 var v = snake_case ? unsnake(k) : k;
60963                 return {
60964                     key: k,
60965                     value: v,
60966                     title: isMulti ? v : d.title
60967                 };
60968             });
60969             comboData = objectDifference(comboData, multiData);
60970             if (callback) callback(comboData);
60971         });
60972     }
60973
60974
60975     function setPlaceholder(d) {
60976         var ph;
60977         if (isMulti) {
60978             ph = field.placeholder() || t('inspector.add');
60979         } else {
60980             var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
60981                 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
60982             ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
60983         }
60984
60985         container.selectAll('input')
60986             .attr('placeholder', ph + '…');
60987     }
60988
60989
60990     function change() {
60991         var val = tagValue(utilGetSetValue(input)),
60992             t$$1 = {};
60993
60994         if (isMulti) {
60995             if (!val) return;
60996             container.classed('active', false);
60997             utilGetSetValue(input, '');
60998             field.keys.push(field.key + val);
60999             t$$1[field.key + val] = 'yes';
61000             window.setTimeout(function() { input.node().focus(); }, 10);
61001
61002         } else {
61003             t$$1[field.key] = val;
61004         }
61005
61006         dispatch$$1.call('change', this, t$$1);
61007     }
61008
61009
61010     function removeMultikey(d) {
61011         event.stopPropagation();
61012         var t$$1 = {};
61013         t$$1[d.key] = undefined;
61014         dispatch$$1.call('change', this, t$$1);
61015     }
61016
61017
61018     function combo(selection$$1) {
61019         if (isMulti) {
61020             container = selection$$1.selectAll('ul').data([0]);
61021
61022             container = container.enter()
61023                 .append('ul')
61024                 .attr('class', 'form-field-multicombo')
61025                 .on('click', function() {
61026                     window.setTimeout(function() { input.node().focus(); }, 10);
61027                 })
61028                 .merge(container);
61029
61030         } else {
61031             container = selection$$1;
61032         }
61033
61034         input = container.selectAll('input')
61035             .data([0]);
61036
61037         input = input.enter()
61038             .append('input')
61039             .attr('type', 'text')
61040             .attr('id', 'preset-input-' + field.id)
61041             .call(initCombo, selection$$1)
61042             .merge(input);
61043
61044         if (isNetwork && nominatim && entity) {
61045             var center = entity.extent(context.graph()).center();
61046             nominatim.countryCode(center, function (err, code) {
61047                 country = code;
61048             });
61049         }
61050
61051         input
61052             .on('change', change)
61053             .on('blur', change);
61054
61055         if (isMulti) {
61056             combobox
61057                 .on('accept', function() {
61058                     input.node().blur();
61059                     input.node().focus();
61060                 });
61061
61062             input
61063                 .on('focus', function() { container.classed('active', true); });
61064         }
61065     }
61066
61067
61068     combo.tags = function(tags) {
61069         if (isMulti) {
61070             multiData = [];
61071
61072             // Build multiData array containing keys already set..
61073             Object.keys(tags).forEach(function(key) {
61074                 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
61075
61076                 var suffix = key.substring(field.key.length);
61077                 multiData.push({
61078                     key: key,
61079                     value: displayValue(suffix)
61080                 });
61081             });
61082
61083             // Set keys for form-field modified (needed for undo and reset buttons)..
61084             field.keys = lodash.map(multiData, 'key');
61085
61086             // Exclude existing multikeys from combo options..
61087             var available = objectDifference(comboData, multiData);
61088             combobox.data(available);
61089
61090             // Hide 'Add' button if this field uses fixed set of
61091             // translateable optstrings and they're all currently used..
61092             container.selectAll('.combobox-input, .combobox-caret')
61093                 .classed('hide', optstrings && !available.length);
61094
61095
61096             // Render chips
61097             var chips = container.selectAll('.chips')
61098                 .data(multiData);
61099
61100             chips.exit()
61101                 .remove();
61102
61103             var enter = chips.enter()
61104                 .insert('li', 'input')
61105                 .attr('class', 'chips');
61106
61107             enter.append('span');
61108             enter.append('a');
61109
61110             chips = chips.merge(enter);
61111
61112             chips.select('span')
61113                 .text(function(d) { return d.value; });
61114
61115             chips.select('a')
61116                 .on('click', removeMultikey)
61117                 .attr('class', 'remove')
61118                 .text('×');
61119
61120         } else {
61121             utilGetSetValue(input, displayValue(tags[field.key]));
61122         }
61123     };
61124
61125
61126     combo.focus = function() {
61127         input.node().focus();
61128     };
61129
61130
61131     combo.entity = function(_) {
61132         if (!arguments.length) return entity;
61133         entity = _;
61134         return combo;
61135     };
61136
61137
61138     return utilRebind(combo, dispatch$$1, 'on');
61139 }
61140
61141 function uiFieldText(field, context) {
61142     var dispatch$$1 = dispatch('change'),
61143         nominatim = services.nominatim,
61144         input,
61145         entity;
61146
61147
61148     function i(selection$$1) {
61149         var fieldId = 'preset-input-' + field.id;
61150
61151         input = selection$$1.selectAll('input')
61152             .data([0]);
61153
61154         input = input.enter()
61155             .append('input')
61156             .attr('type', field.type)
61157             .attr('id', fieldId)
61158             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
61159             .merge(input);
61160
61161         input
61162             .on('input', change(true))
61163             .on('blur', change())
61164             .on('change', change());
61165
61166         if (field.type === 'tel' && nominatim && entity) {
61167             var center = entity.extent(context.graph()).center();
61168             nominatim.countryCode(center, function (err, countryCode) {
61169                 if (err || !dataPhoneFormats[countryCode]) return;
61170                 selection$$1.selectAll('#' + fieldId)
61171                     .attr('placeholder', dataPhoneFormats[countryCode]);
61172             });
61173
61174         } else if (field.type === 'number') {
61175             input.attr('type', 'text');
61176
61177             var spinControl = selection$$1.selectAll('.spin-control')
61178                 .data([0]);
61179
61180             var enter = spinControl.enter()
61181                 .append('div')
61182                 .attr('class', 'spin-control');
61183
61184             enter
61185                 .append('button')
61186                 .datum(1)
61187                 .attr('class', 'increment')
61188                 .attr('tabindex', -1);
61189
61190             enter
61191                 .append('button')
61192                 .datum(-1)
61193                 .attr('class', 'decrement')
61194                 .attr('tabindex', -1);
61195
61196             spinControl = spinControl
61197                 .merge(enter);
61198
61199             spinControl.selectAll('button')
61200                 .on('click', function(d) {
61201                     event.preventDefault();
61202                     var num = parseInt(input.node().value || 0, 10);
61203                     if (!isNaN(num)) input.node().value = num + d;
61204                     change()();
61205                 });
61206         }
61207     }
61208
61209
61210     function change(onInput) {
61211         return function() {
61212             var t$$1 = {};
61213             t$$1[field.key] = utilGetSetValue(input) || undefined;
61214             dispatch$$1.call('change', this, t$$1, onInput);
61215         };
61216     }
61217
61218
61219     i.entity = function(_) {
61220         if (!arguments.length) return entity;
61221         entity = _;
61222         return i;
61223     };
61224
61225
61226     i.tags = function(tags) {
61227         utilGetSetValue(input, tags[field.key] || '');
61228     };
61229
61230
61231     i.focus = function() {
61232         var node = input.node();
61233         if (node) node.focus();
61234     };
61235
61236     return utilRebind(i, dispatch$$1, 'on');
61237 }
61238
61239 function uiFieldAccess(field) {
61240     var dispatch$$1 = dispatch('change'),
61241         items;
61242
61243     function access(selection$$1) {
61244         var wrap = selection$$1.selectAll('.preset-input-wrap')
61245             .data([0]);
61246
61247         wrap = wrap.enter()
61248             .append('div')
61249             .attr('class', 'cf preset-input-wrap')
61250             .append('ul')
61251             .merge(wrap);
61252
61253         var list = wrap.selectAll('ul')
61254             .data([0]);
61255
61256         list = list.enter()
61257             .append('ul')
61258             .merge(list);
61259
61260
61261         items = list.selectAll('li')
61262             .data(field.keys);
61263
61264         // Enter
61265         var enter = items.enter()
61266             .append('li')
61267             .attr('class', function(d) { return 'cf preset-access-' + d; });
61268
61269         enter
61270             .append('span')
61271             .attr('class', 'col6 label preset-label-access')
61272             .attr('for', function(d) { return 'preset-input-access-' + d; })
61273             .text(function(d) { return field.t('types.' + d); });
61274
61275         enter
61276             .append('div')
61277             .attr('class', 'col6 preset-input-access-wrap')
61278             .append('input')
61279             .attr('type', 'text')
61280             .attr('class', 'preset-input-access')
61281             .attr('id', function(d) { return 'preset-input-access-' + d; })
61282             .each(function(d) {
61283                 select(this)
61284                     .call(d3combobox()
61285                         .data(access.options(d)));
61286             });
61287
61288
61289         // Update
61290         items = items.merge(enter);
61291
61292         wrap.selectAll('.preset-input-access')
61293             .on('change', change)
61294             .on('blur', change);
61295     }
61296
61297
61298     function change(d) {
61299         var tag = {};
61300         tag[d] = utilGetSetValue(select(this)) || undefined;
61301         dispatch$$1.call('change', this, tag);
61302     }
61303
61304
61305     access.options = function(type) {
61306         var options = ['no', 'permissive', 'private', 'destination'];
61307
61308         if (type !== 'access') {
61309             options.unshift('yes');
61310             options.push('designated');
61311
61312             if (type === 'bicycle') {
61313                 options.push('dismount');
61314             }
61315         }
61316
61317         return options.map(function(option) {
61318             return {
61319                 title: field.t('options.' + option + '.description'),
61320                 value: option
61321             };
61322         });
61323     };
61324
61325
61326     var placeholders = {
61327         footway: {
61328             foot: 'designated',
61329             motor_vehicle: 'no'
61330         },
61331         steps: {
61332             foot: 'yes',
61333             motor_vehicle: 'no',
61334             bicycle: 'no',
61335             horse: 'no'
61336         },
61337         pedestrian: {
61338             foot: 'yes',
61339             motor_vehicle: 'no'
61340         },
61341         cycleway: {
61342             motor_vehicle: 'no',
61343             bicycle: 'designated'
61344         },
61345         bridleway: {
61346             motor_vehicle: 'no',
61347             horse: 'designated'
61348         },
61349         path: {
61350             foot: 'yes',
61351             motor_vehicle: 'no',
61352             bicycle: 'yes',
61353             horse: 'yes'
61354         },
61355         motorway: {
61356             foot: 'no',
61357             motor_vehicle: 'yes',
61358             bicycle: 'no',
61359             horse: 'no'
61360         },
61361         trunk: {
61362             motor_vehicle: 'yes'
61363         },
61364         primary: {
61365             foot: 'yes',
61366             motor_vehicle: 'yes',
61367             bicycle: 'yes',
61368             horse: 'yes'
61369         },
61370         secondary: {
61371             foot: 'yes',
61372             motor_vehicle: 'yes',
61373             bicycle: 'yes',
61374             horse: 'yes'
61375         },
61376         tertiary: {
61377             foot: 'yes',
61378             motor_vehicle: 'yes',
61379             bicycle: 'yes',
61380             horse: 'yes'
61381         },
61382         residential: {
61383             foot: 'yes',
61384             motor_vehicle: 'yes',
61385             bicycle: 'yes',
61386             horse: 'yes'
61387         },
61388         unclassified: {
61389             foot: 'yes',
61390             motor_vehicle: 'yes',
61391             bicycle: 'yes',
61392             horse: 'yes'
61393         },
61394         service: {
61395             foot: 'yes',
61396             motor_vehicle: 'yes',
61397             bicycle: 'yes',
61398             horse: 'yes'
61399         },
61400         motorway_link: {
61401             foot: 'no',
61402             motor_vehicle: 'yes',
61403             bicycle: 'no',
61404             horse: 'no'
61405         },
61406         trunk_link: {
61407             motor_vehicle: 'yes'
61408         },
61409         primary_link: {
61410             foot: 'yes',
61411             motor_vehicle: 'yes',
61412             bicycle: 'yes',
61413             horse: 'yes'
61414         },
61415         secondary_link: {
61416             foot: 'yes',
61417             motor_vehicle: 'yes',
61418             bicycle: 'yes',
61419             horse: 'yes'
61420         },
61421         tertiary_link: {
61422             foot: 'yes',
61423             motor_vehicle: 'yes',
61424             bicycle: 'yes',
61425             horse: 'yes'
61426         }
61427     };
61428
61429
61430     access.tags = function(tags) {
61431         utilGetSetValue(items.selectAll('.preset-input-access'),
61432             function(d) { return tags[d] || ''; })
61433             .attr('placeholder', function() {
61434                 return tags.access ? tags.access : field.placeholder();
61435             });
61436
61437         items.selectAll('#preset-input-access-access')
61438             .attr('placeholder', 'yes');
61439
61440         lodash.forEach(placeholders[tags.highway], function(v, k) {
61441             items.selectAll('#preset-input-access-' + k)
61442                 .attr('placeholder', function() { return (tags.access || v); });
61443         });
61444     };
61445
61446
61447     access.focus = function() {
61448         items.selectAll('.preset-input-access')
61449             .node().focus();
61450     };
61451
61452
61453     return utilRebind(access, dispatch$$1, 'on');
61454 }
61455
61456 function uiFieldAddress(field, context) {
61457     var dispatch$$1 = dispatch('init', 'change'),
61458         nominatim = services.nominatim,
61459         wrap = select(null),
61460         isInitialized = false,
61461         entity;
61462
61463     var widths = {
61464         housenumber: 1/3,
61465         street: 2/3,
61466         city: 2/3,
61467         state: 1/4,
61468         postcode: 1/3
61469     };
61470
61471
61472     function getNearStreets() {
61473         var extent$$1 = entity.extent(context.graph()),
61474             l = extent$$1.center(),
61475             box = geoExtent$$1(l).padByMeters(200);
61476
61477         var streets = context.intersects(box)
61478             .filter(isAddressable)
61479             .map(function(d) {
61480                 var loc = context.projection([
61481                     (extent$$1[0][0] + extent$$1[1][0]) / 2,
61482                     (extent$$1[0][1] + extent$$1[1][1]) / 2]),
61483                     choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
61484                 return {
61485                     title: d.tags.name,
61486                     value: d.tags.name,
61487                     dist: choice.distance
61488                 };
61489             })
61490             .sort(function(a, b) {
61491                 return a.dist - b.dist;
61492             });
61493
61494         return lodash.uniqBy(streets, 'value');
61495
61496         function isAddressable(d) {
61497             return d.tags.highway && d.tags.name && d.type === 'way';
61498         }
61499     }
61500
61501
61502     function getNearCities() {
61503         var extent$$1 = entity.extent(context.graph()),
61504             l = extent$$1.center(),
61505             box = geoExtent$$1(l).padByMeters(200);
61506
61507         var cities = context.intersects(box)
61508             .filter(isAddressable)
61509             .map(function(d) {
61510                 return {
61511                     title: d.tags['addr:city'] || d.tags.name,
61512                     value: d.tags['addr:city'] || d.tags.name,
61513                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
61514                 };
61515             })
61516             .sort(function(a, b) {
61517                 return a.dist - b.dist;
61518             });
61519
61520         return lodash.uniqBy(cities, 'value');
61521
61522
61523         function isAddressable(d) {
61524             if (d.tags.name &&
61525                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
61526                 return true;
61527
61528             if (d.tags.place && d.tags.name && (
61529                     d.tags.place === 'city' ||
61530                     d.tags.place === 'town' ||
61531                     d.tags.place === 'village'))
61532                 return true;
61533
61534             if (d.tags['addr:city']) return true;
61535
61536             return false;
61537         }
61538     }
61539
61540
61541     function getNearValues(key) {
61542         var extent$$1 = entity.extent(context.graph()),
61543             l = extent$$1.center(),
61544             box = geoExtent$$1(l).padByMeters(200);
61545
61546         var results = context.intersects(box)
61547             .filter(function hasTag(d) {
61548                 return d.tags[key];
61549             })
61550             .map(function(d) {
61551                 return {
61552                     title: d.tags[key],
61553                     value: d.tags[key],
61554                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
61555                 };
61556             })
61557             .sort(function(a, b) {
61558                 return a.dist - b.dist;
61559             });
61560
61561         return lodash.uniqBy(results, 'value');
61562     }
61563
61564
61565     function initCallback(err, countryCode) {
61566         if (err) return;
61567
61568         var addressFormat = lodash.find(dataAddressFormats, function (a) {
61569             return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode);
61570         }) || lodash.first(dataAddressFormats);
61571
61572         function row(r) {
61573             // Normalize widths.
61574             var total = lodash.reduce(r, function(sum$$1, field) {
61575                 return sum$$1 + (widths[field] || 0.5);
61576             }, 0);
61577
61578             return r.map(function (field) {
61579                 return {
61580                     id: field,
61581                     width: (widths[field] || 0.5) / total
61582                 };
61583             });
61584         }
61585
61586         wrap.selectAll('div')
61587             .data(addressFormat.format)
61588             .enter()
61589             .append('div')
61590             .attr('class', 'addr-row')
61591             .selectAll('input')
61592             .data(row)
61593             .enter()
61594             .append('input')
61595             .property('type', 'text')
61596             .attr('placeholder', function (d) { return field.t('placeholders.' + d.id); })
61597             .attr('class', function (d) { return 'addr-' + d.id; })
61598             .style('width', function (d) { return d.width * 100 + '%'; });
61599
61600         // Update
61601         // setup dropdowns for common address tags
61602         var addrTags = [
61603             'street', 'city', 'state', 'province', 'district',
61604             'subdistrict', 'suburb', 'place', 'postcode'
61605         ];
61606
61607         addrTags.forEach(function(tag) {
61608             var nearValues = (tag === 'street') ? getNearStreets
61609                     : (tag === 'city') ? getNearCities
61610                     : getNearValues;
61611
61612             wrap.selectAll('.addr-' + tag)
61613                 .call(d3combobox()
61614                     .minItems(1)
61615                     .fetcher(function(value, callback) {
61616                         callback(nearValues('addr:' + tag));
61617                     }));
61618         });
61619
61620         wrap.selectAll('input')
61621             .on('blur', change())
61622             .on('change', change());
61623
61624         wrap.selectAll('input:not(.combobox-input)')
61625             .on('input', change(true));
61626
61627         dispatch$$1.call('init');
61628         isInitialized = true;
61629     }
61630
61631
61632     function address(selection$$1) {
61633         isInitialized = false;
61634
61635         wrap = selection$$1.selectAll('.preset-input-wrap')
61636             .data([0]);
61637
61638         wrap = wrap.enter()
61639             .append('div')
61640             .attr('class', 'preset-input-wrap')
61641             .merge(wrap);
61642
61643
61644         if (nominatim && entity) {
61645             var center = entity.extent(context.graph()).center();
61646             nominatim.countryCode(center, initCallback);
61647         }
61648     }
61649
61650
61651     function change(onInput) {
61652         return function() {
61653             var tags = {};
61654
61655             wrap.selectAll('input')
61656                 .each(function (field) {
61657                     tags['addr:' + field.id] = this.value || undefined;
61658                 });
61659
61660             dispatch$$1.call('change', this, tags, onInput);
61661         };
61662     }
61663
61664
61665     function updateTags(tags) {
61666         utilGetSetValue(wrap.selectAll('input'), function (field) {
61667             return tags['addr:' + field.id] || '';
61668         });
61669     }
61670
61671
61672     address.entity = function(_) {
61673         if (!arguments.length) return entity;
61674         entity = _;
61675         return address;
61676     };
61677
61678
61679     address.tags = function(tags) {
61680         if (isInitialized) {
61681             updateTags(tags);
61682         } else {
61683             dispatch$$1.on('init', function () {
61684                 updateTags(tags);
61685             });
61686         }
61687     };
61688
61689
61690     address.focus = function() {
61691         var node = wrap.selectAll('input').node();
61692         if (node) node.focus();
61693     };
61694
61695
61696     return utilRebind(address, dispatch$$1, 'on');
61697 }
61698
61699 function uiFieldCycleway(field) {
61700     var dispatch$$1 = dispatch('change'),
61701         items = select(null);
61702
61703
61704     function cycleway(selection$$1) {
61705
61706         function stripcolon(s) {
61707             return s.replace(':', '');
61708         }
61709
61710
61711         var wrap = selection$$1.selectAll('.preset-input-wrap')
61712             .data([0]);
61713
61714         wrap = wrap.enter()
61715             .append('div')
61716             .attr('class', 'cf preset-input-wrap')
61717             .merge(wrap);
61718
61719
61720         var div = wrap.selectAll('ul')
61721             .data([0]);
61722
61723         div = div.enter()
61724             .append('ul')
61725             .merge(div);
61726
61727
61728         items = div.selectAll('li')
61729             .data(field.keys);
61730
61731         var enter = items.enter()
61732             .append('li')
61733             .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
61734
61735         enter
61736             .append('span')
61737             .attr('class', 'col6 label preset-label-cycleway')
61738             .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
61739             .text(function(d) { return field.t('types.' + d); });
61740
61741         enter
61742             .append('div')
61743             .attr('class', 'col6 preset-input-cycleway-wrap')
61744             .append('input')
61745             .attr('type', 'text')
61746             .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
61747             .each(function(d) {
61748                 select(this).call(d3combobox().data(cycleway.options(d)));
61749             });
61750
61751
61752         // Update
61753         wrap.selectAll('.preset-input-cycleway')
61754             .on('change', change)
61755             .on('blur', change);
61756     }
61757
61758
61759     function change() {
61760         var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
61761             right = utilGetSetValue(select('.preset-input-cyclewayright')),
61762             tag = {};
61763
61764         if (left === 'none' || left === '') { left = undefined; }
61765         if (right === 'none' || right === '') { right = undefined; }
61766
61767         // Always set both left and right as changing one can affect the other
61768         tag = {
61769             cycleway: undefined,
61770             'cycleway:left': left,
61771             'cycleway:right': right
61772         };
61773
61774         // If the left and right tags match, use the cycleway tag to tag both
61775         // sides the same way
61776         if (left === right) {
61777             tag = {
61778                 cycleway: left,
61779                 'cycleway:left': undefined,
61780                 'cycleway:right': undefined
61781             };
61782         }
61783
61784         dispatch$$1.call('change', this, tag);
61785     }
61786
61787
61788     cycleway.options = function() {
61789         return keys(field.strings.options).map(function(option) {
61790             return {
61791                 title: field.t('options.' + option + '.description'),
61792                 value: option
61793             };
61794         });
61795     };
61796
61797
61798     cycleway.tags = function(tags) {
61799         utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
61800                 // If cycleway is set, always return that
61801                 if (tags.cycleway) {
61802                     return tags.cycleway;
61803                 }
61804                 return tags[d] || '';
61805             })
61806             .attr('placeholder', field.placeholder());
61807     };
61808
61809
61810     cycleway.focus = function() {
61811         items.selectAll('.preset-input-cycleway')
61812             .node().focus();
61813     };
61814
61815
61816     return utilRebind(cycleway, dispatch$$1, 'on');
61817 }
61818
61819 function uiFieldLanes(field, context) {
61820     var dispatch$$1 = dispatch('change'),
61821         LANE_WIDTH = 40,
61822         LANE_HEIGHT = 200,
61823         wayID,
61824         lanesData;
61825
61826     function lanes(selection$$1) {
61827         lanesData = context.entity(wayID).lanes();
61828
61829         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
61830             selection$$1.call(lanes.off);
61831             return;
61832         }
61833
61834         var wrap = selection$$1.selectAll('.preset-input-wrap')
61835             .data([0]);
61836
61837         wrap = wrap.enter()
61838             .append('div')
61839             .attr('class', 'preset-input-wrap')
61840             .merge(wrap);
61841
61842         var surface =  wrap.selectAll('.surface')
61843             .data([0]);
61844
61845         var d = utilGetDimensions(wrap);
61846         var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
61847
61848         surface = surface.enter()
61849             .append('svg')
61850             .attr('width', d[0])
61851             .attr('height', 300)
61852             .attr('class', 'surface')
61853             .merge(surface);
61854
61855
61856         var lanesSelection = surface.selectAll('.lanes')
61857             .data([0]);
61858
61859         lanesSelection = lanesSelection.enter()
61860             .append('g')
61861             .attr('class', 'lanes')
61862             .merge(lanesSelection);
61863
61864         lanesSelection
61865             .attr('transform', function () {
61866                 return 'translate(' + (freeSpace / 2) + ', 0)';
61867             });
61868
61869
61870         var lane = lanesSelection.selectAll('.lane')
61871            .data(lanesData.lanes);
61872
61873         lane.exit()
61874             .remove();
61875
61876         var enter = lane.enter()
61877             .append('g')
61878             .attr('class', 'lane');
61879
61880         enter
61881             .append('g')
61882             .append('rect')
61883             .attr('y', 50)
61884             .attr('width', LANE_WIDTH)
61885             .attr('height', LANE_HEIGHT);
61886
61887         enter
61888             .append('g')
61889             .attr('class', 'forward')
61890             .append('text')
61891             .attr('y', 40)
61892             .attr('x', 14)
61893             .text('▲');
61894
61895         enter
61896             .append('g')
61897             .attr('class', 'bothways')
61898             .append('text')
61899             .attr('y', 40)
61900             .attr('x', 14)
61901             .text('▲▼');
61902
61903         enter
61904             .append('g')
61905             .attr('class', 'backward')
61906             .append('text')
61907             .attr('y', 40)
61908             .attr('x', 14)
61909             .text('▼');
61910
61911
61912         lane = lane
61913             .merge(enter);
61914
61915         lane
61916             .attr('transform', function(d) {
61917                 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
61918             });
61919
61920         lane.select('.forward')
61921             .style('visibility', function(d) {
61922                 return d.direction === 'forward' ? 'visible' : 'hidden';
61923             });
61924
61925         lane.select('.bothways')
61926             .style('visibility', function(d) {
61927                 return d.direction === 'bothways' ? 'visible' : 'hidden';
61928             });
61929
61930         lane.select('.backward')
61931             .style('visibility', function(d) {
61932                 return d.direction === 'backward' ? 'visible' : 'hidden';
61933             });
61934     }
61935
61936
61937     lanes.entity = function(_) {
61938         if (!wayID || wayID !== _.id) {
61939             wayID = _.id;
61940         }
61941     };
61942
61943     lanes.tags = function() {};
61944     lanes.focus = function() {};
61945     lanes.off = function() {};
61946
61947     return utilRebind(lanes, dispatch$$1, 'on');
61948 }
61949
61950 function uiFieldLocalized(field, context) {
61951     var dispatch$$1 = dispatch('change', 'input'),
61952         wikipedia = services.wikipedia,
61953         input = select(null),
61954         localizedInputs = select(null),
61955         wikiTitles,
61956         entity;
61957
61958
61959     function localized(selection$$1) {
61960         input = selection$$1.selectAll('.localized-main')
61961             .data([0]);
61962
61963         input = input.enter()
61964             .append('input')
61965             .attr('type', 'text')
61966             .attr('id', 'preset-input-' + field.id)
61967             .attr('class', 'localized-main')
61968             .attr('placeholder', field.placeholder())
61969             .merge(input);
61970
61971         if (field.id === 'name') {
61972             var preset = context.presets().match(entity, context.graph());
61973             input.call(d3combobox().fetcher(
61974                 utilSuggestNames(preset, dataSuggestions)
61975             ));
61976         }
61977
61978         input
61979             .on('input', change(true))
61980             .on('blur', change())
61981             .on('change', change());
61982
61983
61984         var translateButton = selection$$1.selectAll('.localized-add')
61985             .data([0]);
61986
61987         translateButton = translateButton.enter()
61988             .append('button')
61989             .attr('class', 'button-input-action localized-add minor')
61990             .attr('tabindex', -1)
61991             .call(svgIcon('#icon-plus'))
61992             .call(tooltip()
61993                 .title(t('translate.translate'))
61994                 .placement('left'))
61995             .merge(translateButton);
61996
61997         translateButton
61998             .on('click', addNew);
61999
62000
62001         localizedInputs = selection$$1.selectAll('.localized-wrap')
62002             .data([0]);
62003
62004         localizedInputs = localizedInputs.enter().append('div')
62005             .attr('class', 'localized-wrap')
62006             .merge(localizedInputs);
62007     }
62008
62009
62010     function addNew() {
62011         event.preventDefault();
62012         var data$$1 = localizedInputs.selectAll('div.entry').data();
62013         var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
62014         var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
62015         var isLangEn = defaultLang.indexOf('en') > -1;
62016         if (isLangEn || langExists) {
62017             defaultLang = '';
62018         }
62019         data$$1.push({ lang: defaultLang, value: '' });
62020         localizedInputs.call(render, data$$1);
62021     }
62022
62023
62024     function change(onInput) {
62025         return function() {
62026             var t$$1 = {};
62027             t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
62028             dispatch$$1.call('change', this, t$$1, onInput);
62029         };
62030     }
62031
62032
62033     function key(lang) {
62034         return field.key + ':' + lang;
62035     }
62036
62037
62038     function changeLang(d) {
62039         var lang = utilGetSetValue(select(this)),
62040             t$$1 = {},
62041             language = lodash.find(dataWikipedia, function(d) {
62042                 return d[0].toLowerCase() === lang.toLowerCase() ||
62043                     d[1].toLowerCase() === lang.toLowerCase();
62044             });
62045
62046         if (language) lang = language[2];
62047
62048         if (d.lang && d.lang !== lang) {
62049             t$$1[key(d.lang)] = undefined;
62050         }
62051
62052         var value = utilGetSetValue(select(this.parentNode)
62053             .selectAll('.localized-value'));
62054
62055         if (lang && value) {
62056             t$$1[key(lang)] = value;
62057         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
62058             t$$1[key(lang)] = wikiTitles[d.lang];
62059         }
62060
62061         d.lang = lang;
62062         dispatch$$1.call('change', this, t$$1);
62063     }
62064
62065
62066     function changeValue(d) {
62067         if (!d.lang) return;
62068         var t$$1 = {};
62069         t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
62070         dispatch$$1.call('change', this, t$$1);
62071     }
62072
62073
62074     function fetcher(value, cb) {
62075         var v = value.toLowerCase();
62076
62077         cb(dataWikipedia.filter(function(d) {
62078             return d[0].toLowerCase().indexOf(v) >= 0 ||
62079             d[1].toLowerCase().indexOf(v) >= 0 ||
62080             d[2].toLowerCase().indexOf(v) >= 0;
62081         }).map(function(d) {
62082             return { value: d[1] };
62083         }));
62084     }
62085
62086
62087     function render(selection$$1, data$$1) {
62088         var wraps = selection$$1.selectAll('div.entry').
62089             data(data$$1, function(d) { return d.lang; });
62090
62091         wraps.exit()
62092             .transition()
62093             .duration(200)
62094             .style('max-height','0px')
62095             .style('opacity', '0')
62096             .style('top','-10px')
62097             .remove();
62098
62099         var innerWrap = wraps.enter()
62100             .insert('div', ':first-child');
62101
62102         innerWrap.attr('class', 'entry')
62103             .each(function() {
62104                 var wrap = select(this);
62105                 var langcombo = d3combobox().fetcher(fetcher).minItems(0);
62106
62107                 var label = wrap
62108                     .append('label')
62109                     .attr('class','form-label')
62110                     .text(t('translate.localized_translation_label'))
62111                     .attr('for','localized-lang');
62112
62113                 label
62114                     .append('button')
62115                     .attr('class', 'minor remove')
62116                     .on('click', function(d){
62117                         event.preventDefault();
62118                         var t$$1 = {};
62119                         t$$1[key(d.lang)] = undefined;
62120                         dispatch$$1.call('change', this, t$$1);
62121                         select(this.parentNode.parentNode)
62122                             .style('top','0')
62123                             .style('max-height','240px')
62124                             .transition()
62125                             .style('opacity', '0')
62126                             .style('max-height','0px')
62127                             .remove();
62128                     })
62129                     .call(svgIcon('#operation-delete'));
62130
62131                 wrap
62132                     .append('input')
62133                     .attr('class', 'localized-lang')
62134                     .attr('type', 'text')
62135                     .attr('placeholder',t('translate.localized_translation_language'))
62136                     .on('blur', changeLang)
62137                     .on('change', changeLang)
62138                     .call(langcombo);
62139
62140                 wrap
62141                     .append('input')
62142                     .on('blur', changeValue)
62143                     .on('change', changeValue)
62144                     .attr('type', 'text')
62145                     .attr('placeholder', t('translate.localized_translation_name'))
62146                     .attr('class', 'localized-value');
62147             });
62148
62149         innerWrap
62150             .style('margin-top', '0px')
62151             .style('max-height', '0px')
62152             .style('opacity', '0')
62153             .transition()
62154             .duration(200)
62155             .style('margin-top', '10px')
62156             .style('max-height', '240px')
62157             .style('opacity', '1')
62158             .on('end', function() {
62159                 select(this)
62160                     .style('max-height', '')
62161                     .style('overflow', 'visible');
62162             });
62163
62164
62165         var entry = selection$$1.selectAll('.entry');
62166
62167         utilGetSetValue(entry.select('.localized-lang'), function(d) {
62168                 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
62169                 return lang ? lang[1] : d.lang;
62170             });
62171
62172         utilGetSetValue(entry.select('.localized-value'),
62173             function(d) { return d.value; });
62174     }
62175
62176
62177     localized.tags = function(tags) {
62178         // Fetch translations from wikipedia
62179         if (tags.wikipedia && !wikiTitles) {
62180             wikiTitles = {};
62181             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
62182             if (wm && wm[0] && wm[1]) {
62183                 wikipedia.translations(wm[1], wm[2], function(d) {
62184                     wikiTitles = d;
62185                 });
62186             }
62187         }
62188
62189         utilGetSetValue(input, tags[field.key] || '');
62190
62191         var postfixed = [], k, m;
62192         for (k in tags) {
62193             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
62194             if (m && m[1] === field.key && m[2]) {
62195                 postfixed.push({ lang: m[2], value: tags[k] });
62196             }
62197         }
62198
62199         localizedInputs.call(render, postfixed.reverse());
62200     };
62201
62202
62203     localized.focus = function() {
62204         input.node().focus();
62205     };
62206
62207
62208     localized.entity = function(_) {
62209         if (!arguments.length) return entity;
62210         entity = _;
62211         return localized;
62212     };
62213
62214     return utilRebind(localized, dispatch$$1, 'on');
62215 }
62216
62217 function uiFieldMaxspeed(field, context) {
62218     var dispatch$$1 = dispatch('change'),
62219         entity,
62220         isImperial,
62221         unitInput = select(null),
62222         input = select(null),
62223         combobox;
62224
62225     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
62226         imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
62227
62228
62229     function maxspeed(selection$$1) {
62230         combobox = d3combobox();
62231         var unitCombobox = d3combobox().data(['km/h', 'mph'].map(comboValues));
62232
62233         input = selection$$1.selectAll('#preset-input-' + field.id)
62234             .data([0]);
62235
62236         input = input.enter()
62237             .append('input')
62238             .attr('type', 'text')
62239             .attr('id', 'preset-input-' + field.id)
62240             .attr('placeholder', field.placeholder())
62241             .call(combobox)
62242             .merge(input);
62243
62244         input
62245             .on('change', change)
62246             .on('blur', change);
62247
62248         var childNodes = context.graph().childNodes(context.entity(entity.id)),
62249             loc = childNodes[~~(childNodes.length/2)].loc;
62250
62251         isImperial = lodash.some(dataImperial.features, function(f) {
62252             return lodash.some(f.geometry.coordinates, function(d) {
62253                 return geoPointInPolygon(loc, d);
62254             });
62255         });
62256
62257         unitInput = selection$$1.selectAll('input.maxspeed-unit')
62258             .data([0]);
62259
62260         unitInput = unitInput.enter()
62261             .append('input')
62262             .attr('type', 'text')
62263             .attr('class', 'maxspeed-unit')
62264             .call(unitCombobox)
62265             .merge(unitInput);
62266
62267         unitInput
62268             .on('blur', changeUnits)
62269             .on('change', changeUnits);
62270
62271
62272         function changeUnits() {
62273             isImperial = utilGetSetValue(unitInput) === 'mph';
62274             utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
62275             setSuggestions();
62276             change();
62277         }
62278     }
62279
62280
62281     function setSuggestions() {
62282         combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
62283         utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
62284     }
62285
62286
62287     function comboValues(d) {
62288         return {
62289             value: d.toString(),
62290             title: d.toString()
62291         };
62292     }
62293
62294
62295     function change() {
62296         var tag = {},
62297             value = utilGetSetValue(input);
62298
62299         if (!value) {
62300             tag[field.key] = undefined;
62301         } else if (isNaN(value) || !isImperial) {
62302             tag[field.key] = value;
62303         } else {
62304             tag[field.key] = value + ' mph';
62305         }
62306
62307         dispatch$$1.call('change', this, tag);
62308     }
62309
62310
62311     maxspeed.tags = function(tags) {
62312         var value = tags[field.key];
62313
62314         if (value && value.indexOf('mph') >= 0) {
62315             value = parseInt(value, 10);
62316             isImperial = true;
62317         } else if (value) {
62318             isImperial = false;
62319         }
62320
62321         setSuggestions();
62322         utilGetSetValue(input, value || '');
62323     };
62324
62325
62326     maxspeed.focus = function() {
62327         input.node().focus();
62328     };
62329
62330
62331     maxspeed.entity = function(_) {
62332         entity = _;
62333     };
62334
62335
62336     return utilRebind(maxspeed, dispatch$$1, 'on');
62337 }
62338
62339 function uiFieldRadio(field) {
62340     var dispatch$$1 = dispatch('change'),
62341         placeholder = select(null),
62342         labels = select(null),
62343         radios = select(null);
62344
62345
62346     function radio(selection$$1) {
62347         selection$$1.classed('preset-radio', true);
62348
62349         var wrap = selection$$1.selectAll('.preset-input-wrap')
62350             .data([0]);
62351
62352         var enter = wrap.enter()
62353             .append('div')
62354             .attr('class', 'preset-input-wrap toggle-list');
62355
62356         enter
62357             .append('span')
62358             .attr('class', 'placeholder');
62359
62360         wrap = wrap
62361             .merge(enter);
62362
62363
62364         placeholder = wrap.selectAll('.placeholder');
62365
62366         labels = wrap.selectAll('label')
62367             .data(field.options || field.keys);
62368
62369         enter = labels.enter()
62370             .append('label');
62371
62372         enter.append('input')
62373             .attr('type', 'radio')
62374             .attr('name', field.id)
62375             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
62376             .attr('checked', false);
62377
62378         enter.append('span')
62379             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
62380
62381         labels = labels
62382             .merge(enter);
62383
62384         radios = labels.selectAll('input')
62385             .on('change', change);
62386     }
62387
62388
62389     function change() {
62390         var t$$1 = {};
62391         if (field.key) t$$1[field.key] = undefined;
62392         radios.each(function(d) {
62393             var active$$1 = select(this).property('checked');
62394             if (field.key) {
62395                 if (active$$1) t$$1[field.key] = d;
62396             } else {
62397                 t$$1[d] = active$$1 ? 'yes' : undefined;
62398             }
62399         });
62400         dispatch$$1.call('change', this, t$$1);
62401     }
62402
62403
62404     radio.tags = function(tags) {
62405         function checked(d) {
62406             if (field.key) {
62407                 return tags[field.key] === d;
62408             } else {
62409                 return !!(tags[d] && tags[d] !== 'no');
62410             }
62411         }
62412
62413         labels.classed('active', checked);
62414         radios.property('checked', checked);
62415         var selection$$1 = radios.filter(function() { return this.checked; });
62416         if (selection$$1.empty()) {
62417             placeholder.text(t('inspector.none'));
62418         } else {
62419             placeholder.text(selection$$1.attr('value'));
62420         }
62421     };
62422
62423
62424     radio.focus = function() {
62425         radios.node().focus();
62426     };
62427
62428
62429     return utilRebind(radio, dispatch$$1, 'on');
62430 }
62431
62432 function uiFieldRestrictions(field, context) {
62433     var dispatch$$1 = dispatch('change'),
62434         breathe = behaviorBreathe(context),
62435         hover = behaviorHover(context),
62436         initialized = false,
62437         vertexID,
62438         fromNodeID;
62439
62440
62441     function restrictions(selection$$1) {
62442         // if form field is hidden or has detached from dom, clean up.
62443         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
62444             selection$$1.call(restrictions.off);
62445             return;
62446         }
62447
62448         var wrap = selection$$1.selectAll('.preset-input-wrap')
62449             .data([0]);
62450
62451         var enter = wrap.enter()
62452             .append('div')
62453             .attr('class', 'preset-input-wrap');
62454
62455         enter
62456             .append('div')
62457             .attr('class', 'restriction-help');
62458
62459
62460         var intersection = osmIntersection(context.graph(), vertexID),
62461             graph = intersection.graph,
62462             vertex = graph.entity(vertexID),
62463             filter = utilFunctor(true),
62464             extent$$1 = geoExtent$$1(),
62465             projection = geoRawMercator();
62466
62467         var d = utilGetDimensions(wrap.merge(enter)),
62468             c = [d[0] / 2, d[1] / 2],
62469             z = 24;
62470
62471         projection
62472             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
62473
62474         var s = projection(vertex.loc);
62475
62476         projection
62477             .translate([c[0] - s[0], c[1] - s[1]])
62478             .clipExtent([[0, 0], d]);
62479
62480         var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
62481             drawVertices = svgVertices$$1(projection, context),
62482             drawLines = svgLines$$1(projection, context),
62483             drawTurns = svgTurns(projection, context);
62484
62485         enter
62486             .call(drawLayers);
62487
62488         wrap = wrap
62489             .merge(enter);
62490
62491         var surface = wrap.selectAll('.surface');
62492
62493         if (!enter.empty()) {
62494             initialized = true;
62495             surface
62496                 .call(breathe)
62497                 .call(hover);
62498         }
62499
62500         surface
62501             .call(utilSetDimensions, d)
62502             .call(drawVertices, graph, [vertex], filter, extent$$1, z)
62503             .call(drawLines, graph, intersection.ways, filter)
62504             .call(drawTurns, graph, intersection.turns(fromNodeID));
62505
62506         surface
62507             .on('click.restrictions', click)
62508             .on('mouseover.restrictions', mouseover)
62509             .on('mouseout.restrictions', mouseout);
62510
62511         surface
62512             .selectAll('.selected')
62513             .classed('selected', false);
62514
62515         if (fromNodeID) {
62516             surface
62517                 .selectAll('.' + intersection.highways[fromNodeID].id)
62518                 .classed('selected', true);
62519         }
62520
62521         mouseout();
62522
62523         context.history()
62524             .on('change.restrictions', render);
62525
62526         select(window)
62527             .on('resize.restrictions', function() {
62528                 utilSetDimensions(wrap, null);
62529                 render();
62530             });
62531
62532
62533         function click() {
62534             surface
62535                 .call(breathe.off)
62536                 .call(breathe);
62537
62538             var datum = event.target.__data__;
62539             if (datum instanceof osmEntity$$1) {
62540                 fromNodeID = intersection.adjacentNodeId(datum.id);
62541                 render();
62542             } else if (datum instanceof osmTurn) {
62543                 if (datum.restriction) {
62544                     context.perform(
62545                         actionUnrestrictTurn(datum, projection),
62546                         t('operations.restriction.annotation.delete')
62547                     );
62548                 } else {
62549                     context.perform(
62550                         actionRestrictTurn(datum, projection),
62551                         t('operations.restriction.annotation.create')
62552                     );
62553                 }
62554             }
62555         }
62556
62557
62558         function mouseover() {
62559             var datum = event.target.__data__;
62560             if (datum instanceof osmTurn) {
62561                 var graph = context.graph(),
62562                     presets = context.presets(),
62563                     preset;
62564
62565                 if (datum.restriction) {
62566                     preset = presets.match(graph.entity(datum.restriction), graph);
62567                 } else {
62568                     preset = presets.item('type/restriction/' +
62569                         osmInferRestriction(
62570                             graph,
62571                             datum.from,
62572                             datum.via,
62573                             datum.to,
62574                             projection
62575                         )
62576                     );
62577                 }
62578
62579                 wrap.selectAll('.restriction-help')
62580                     .text(t('operations.restriction.help.' +
62581                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
62582                         { restriction: preset.name() })
62583                     );
62584             }
62585         }
62586
62587
62588         function mouseout() {
62589             wrap.selectAll('.restriction-help')
62590                 .text(t('operations.restriction.help.' +
62591                     (fromNodeID ? 'toggle' : 'select'))
62592                 );
62593         }
62594
62595
62596         function render() {
62597             if (context.hasEntity(vertexID)) {
62598                 restrictions(selection$$1);
62599             }
62600         }
62601     }
62602
62603
62604     restrictions.entity = function(_) {
62605         if (!vertexID || vertexID !== _.id) {
62606             fromNodeID = null;
62607             vertexID = _.id;
62608         }
62609     };
62610
62611
62612     restrictions.tags = function() {};
62613     restrictions.focus = function() {};
62614
62615
62616     restrictions.off = function(selection$$1) {
62617         if (!initialized) return;
62618
62619         selection$$1.selectAll('.surface')
62620             .call(hover.off)
62621             .call(breathe.off)
62622             .on('click.restrictions', null)
62623             .on('mouseover.restrictions', null)
62624             .on('mouseout.restrictions', null);
62625
62626         context.history()
62627             .on('change.restrictions', null);
62628
62629         select(window)
62630             .on('resize.restrictions', null);
62631     };
62632
62633
62634     return utilRebind(restrictions, dispatch$$1, 'on');
62635 }
62636
62637 function uiFieldTextarea(field) {
62638     var dispatch$$1 = dispatch('change'),
62639         input = select(null);
62640
62641
62642     function textarea(selection$$1) {
62643         input = selection$$1.selectAll('textarea')
62644             .data([0]);
62645
62646         input = input.enter()
62647             .append('textarea')
62648             .attr('id', 'preset-input-' + field.id)
62649             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
62650             .attr('maxlength', 255)
62651             .on('input', change(true))
62652             .on('blur', change())
62653             .on('change', change())
62654             .merge(input);
62655     }
62656
62657
62658     function change(onInput) {
62659         return function() {
62660             var t$$1 = {};
62661             t$$1[field.key] = utilGetSetValue(input) || undefined;
62662             dispatch$$1.call('change', this, t$$1, onInput);
62663         };
62664     }
62665
62666
62667     textarea.tags = function(tags) {
62668         utilGetSetValue(input, tags[field.key] || '');
62669     };
62670
62671
62672     textarea.focus = function() {
62673         input.node().focus();
62674     };
62675
62676
62677     return utilRebind(textarea, dispatch$$1, 'on');
62678 }
62679
62680 function uiFieldWikipedia(field, context) {
62681     var dispatch$$1 = dispatch('change'),
62682         wikipedia = services.wikipedia,
62683         wikidata = services.wikidata,
62684         link = select(null),
62685         lang = select(null),
62686         title = select(null),
62687         entity;
62688
62689
62690     function wiki(selection$$1) {
62691         var langcombo = d3combobox()
62692             .fetcher(function(value, cb) {
62693                 var v = value.toLowerCase();
62694
62695                 cb(dataWikipedia.filter(function(d) {
62696                     return d[0].toLowerCase().indexOf(v) >= 0 ||
62697                         d[1].toLowerCase().indexOf(v) >= 0 ||
62698                         d[2].toLowerCase().indexOf(v) >= 0;
62699                 }).map(function(d) {
62700                     return { value: d[1] };
62701                 }));
62702             });
62703
62704         var titlecombo = d3combobox()
62705             .fetcher(function(value, cb) {
62706                 if (!value) {
62707                     value = context.entity(entity.id).tags.name || '';
62708                 }
62709
62710                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
62711                 searchfn(language()[2], value, function(query, data$$1) {
62712                     cb(data$$1.map(function(d) {
62713                         return { value: d };
62714                     }));
62715                 });
62716             });
62717
62718
62719         lang = selection$$1.selectAll('input.wiki-lang')
62720             .data([0]);
62721
62722         lang = lang.enter()
62723             .append('input')
62724             .attr('type', 'text')
62725             .attr('class', 'wiki-lang')
62726             .attr('placeholder', t('translate.localized_translation_language'))
62727             .merge(lang);
62728
62729         utilGetSetValue(lang, language()[1]);
62730
62731         lang
62732             .call(langcombo)
62733             .on('blur', changeLang)
62734             .on('change', changeLang);
62735
62736
62737         title = selection$$1.selectAll('input.wiki-title')
62738             .data([0]);
62739
62740         title = title.enter()
62741             .append('input')
62742             .attr('type', 'text')
62743             .attr('class', 'wiki-title')
62744             .attr('id', 'preset-input-' + field.id)
62745             .merge(title);
62746
62747         title
62748             .call(titlecombo)
62749             .on('blur', blur)
62750             .on('change', change);
62751
62752
62753         link = selection$$1.selectAll('a.wiki-link')
62754             .data([0]);
62755
62756         link = link.enter()
62757             .append('a')
62758             .attr('class', 'wiki-link button-input-action minor')
62759             .attr('tabindex', -1)
62760             .attr('target', '_blank')
62761             .call(svgIcon('#icon-out-link', 'inline'))
62762             .merge(link);
62763     }
62764
62765
62766     function language() {
62767         var value = utilGetSetValue(lang).toLowerCase();
62768         var locale = utilDetect().locale.toLowerCase();
62769         var localeLanguage;
62770         return lodash.find(dataWikipedia, function(d) {
62771             if (d[2] === locale) localeLanguage = d;
62772             return d[0].toLowerCase() === value ||
62773                 d[1].toLowerCase() === value ||
62774                 d[2] === value;
62775         }) || localeLanguage || ['English', 'English', 'en'];
62776     }
62777
62778
62779     function changeLang() {
62780         utilGetSetValue(lang, language()[1]);
62781         change(true);
62782     }
62783
62784
62785     function blur() {
62786         change(true);
62787     }
62788
62789
62790     function change(skipWikidata) {
62791         var value = utilGetSetValue(title),
62792             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
62793             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
62794             anchor,
62795             syncTags = {};
62796
62797         if (l) {
62798             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
62799             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
62800             if (m[3]) {
62801                 try {
62802                     // Best-effort `anchordecode:` implementation
62803                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
62804                 } catch (e) {
62805                     anchor = decodeURIComponent(m[3]);
62806                 }
62807                 value += '#' + anchor.replace(/_/g, ' ');
62808             }
62809             value = value.slice(0, 1).toUpperCase() + value.slice(1);
62810             utilGetSetValue(lang, l[1]);
62811             utilGetSetValue(title, value);
62812         }
62813
62814         syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
62815         if (!skipWikidata) {
62816             syncTags.wikidata = undefined;
62817         }
62818
62819         dispatch$$1.call('change', this, syncTags);
62820
62821
62822         if (skipWikidata || !value || !language()[2]) return;
62823
62824         // attempt asynchronous update of wikidata tag..
62825         var initEntityId = entity.id,
62826             initWikipedia = context.entity(initEntityId).tags.wikipedia;
62827
62828         wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
62829             if (!data$$1 || !Object.keys(data$$1).length) return;
62830             var qids = Object.keys(data$$1);
62831
62832             // 1. most recent change was a tag change
62833             var annotation = t('operations.change_tags.annotation'),
62834                 currAnnotation = context.history().undoAnnotation();
62835             if (currAnnotation !== annotation) return;
62836
62837             // 2. same entity exists and still selected
62838             var selectedIds = context.selectedIDs(),
62839                 currEntityId = selectedIds.length > 0 && selectedIds[0];
62840             if (currEntityId !== initEntityId) return;
62841
62842             // 3. wikipedia value has not changed
62843             var currTags = lodash.clone(context.entity(currEntityId).tags);
62844             if (initWikipedia !== currTags.wikipedia) return;
62845
62846             // ok to coalesce the update of wikidata tag into the previous tag change
62847             currTags.wikidata = qids && lodash.find(qids, function(id) {
62848                 return id.match(/^Q\d+$/);
62849             });
62850
62851             context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
62852             dispatch$$1.call('change', this, currTags);
62853         });
62854     }
62855
62856
62857     wiki.tags = function(tags) {
62858         var value = tags[field.key] || '',
62859             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
62860             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
62861             anchor = m && m[3];
62862
62863         // value in correct format
62864         if (l) {
62865             utilGetSetValue(lang, l[1]);
62866             utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
62867             if (anchor) {
62868                 try {
62869                     // Best-effort `anchorencode:` implementation
62870                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
62871                 } catch (e) {
62872                     anchor = anchor.replace(/ /g, '_');
62873                 }
62874             }
62875             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
62876                 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
62877
62878         // unrecognized value format
62879         } else {
62880             utilGetSetValue(title, value);
62881             if (value && value !== '') {
62882                 utilGetSetValue(lang, '');
62883             }
62884             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
62885         }
62886     };
62887
62888
62889     wiki.entity = function(_) {
62890         if (!arguments.length) return entity;
62891         entity = _;
62892         return wiki;
62893     };
62894
62895
62896     wiki.focus = function() {
62897         title.node().focus();
62898     };
62899
62900
62901     return utilRebind(wiki, dispatch$$1, 'on');
62902 }
62903
62904 var uiFields = {
62905     access: uiFieldAccess,
62906     address: uiFieldAddress,
62907     check: uiFieldCheck,
62908     defaultcheck: uiFieldCheck,
62909     combo: uiFieldCombo,
62910     typeCombo: uiFieldCombo,
62911     multiCombo: uiFieldCombo,
62912     networkCombo: uiFieldCombo,
62913     cycleway: uiFieldCycleway,
62914     text: uiFieldText,
62915     url: uiFieldText,
62916     number: uiFieldText,
62917     email: uiFieldText,
62918     tel: uiFieldText,
62919     localized: uiFieldLocalized,
62920     lanes: uiFieldLanes,
62921     maxspeed: uiFieldMaxspeed,
62922     radio: uiFieldRadio,
62923     restrictions: uiFieldRestrictions,
62924     textarea: uiFieldTextarea,
62925     wikipedia: uiFieldWikipedia
62926 };
62927
62928 function uiPreset(context) {
62929     var dispatch$$1 = dispatch('change'),
62930         state,
62931         fieldsArr,
62932         preset,
62933         tags,
62934         id;
62935
62936
62937     // Field Constructor
62938     function UIField(field, entity, show) {
62939         field = lodash.clone(field);
62940
62941         field.input = uiFields[field.type](field, context)
62942             .on('change', function(t$$1, onInput) {
62943                 dispatch$$1.call('change', field, t$$1, onInput);
62944             });
62945
62946         if (field.input.entity) field.input.entity(entity);
62947
62948         field.keys = field.keys || [field.key];
62949
62950         field.show = show;
62951
62952         field.shown = function() {
62953             return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
62954         };
62955
62956         field.modified = function() {
62957             var original = context.graph().base().entities[entity.id];
62958             return lodash.some(field.keys, function(key) {
62959                 return original ? tags[key] !== original.tags[key] : tags[key];
62960             });
62961         };
62962
62963         field.revert = function() {
62964             var original = context.graph().base().entities[entity.id],
62965                 t$$1 = {};
62966             field.keys.forEach(function(key) {
62967                 t$$1[key] = original ? original.tags[key] : undefined;
62968             });
62969             return t$$1;
62970         };
62971
62972         field.present = function() {
62973             return lodash.some(field.keys, function(key) {
62974                 return tags[key];
62975             });
62976         };
62977
62978         field.remove = function() {
62979             var t$$1 = {};
62980             field.keys.forEach(function(key) {
62981                 t$$1[key] = undefined;
62982             });
62983             return t$$1;
62984         };
62985
62986         return field;
62987     }
62988
62989
62990     function fieldKey(field) {
62991         return field.id;
62992     }
62993
62994
62995     function presets(selection$$1) {
62996         selection$$1.call(uiDisclosure()
62997             .title(t('inspector.all_fields'))
62998             .expanded(context.storage('preset_fields.expanded') !== 'false')
62999             .on('toggled', toggled)
63000             .content(content)
63001         );
63002
63003         function toggled(expanded) {
63004             context.storage('preset_fields.expanded', expanded);
63005         }
63006     }
63007
63008
63009     function content(selection$$1) {
63010         if (!fieldsArr) {
63011             var entity = context.entity(id),
63012                 geometry = context.geometry(id),
63013                 presets = context.presets();
63014
63015             fieldsArr = [];
63016
63017             if (presets.field('name')) {
63018                 fieldsArr.push(UIField(presets.field('name'), entity));
63019             }
63020
63021             preset.fields.forEach(function(field) {
63022                 if (field.matchGeometry(geometry)) {
63023                     fieldsArr.push(UIField(field, entity, true));
63024                 }
63025             });
63026
63027             if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
63028                 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
63029             }
63030
63031             presets.universal().forEach(function(field) {
63032                 if (preset.fields.indexOf(field) < 0) {
63033                     fieldsArr.push(UIField(field, entity));
63034                 }
63035             });
63036         }
63037
63038         var shown = fieldsArr.filter(function(field) { return field.shown(); }),
63039             notShown = fieldsArr.filter(function(field) { return !field.shown(); });
63040
63041
63042         var form = selection$$1.selectAll('.preset-form')
63043             .data([0]);
63044
63045         form = form.enter()
63046             .append('div')
63047             .attr('class', 'preset-form inspector-inner fillL3')
63048             .merge(form);
63049
63050
63051         var fields = form.selectAll('.form-field')
63052             .data(shown, fieldKey);
63053
63054         fields.exit()
63055             .remove();
63056
63057         // Enter
63058         var enter = fields.enter()
63059             .append('div')
63060             .attr('class', function(field) {
63061                 return 'form-field form-field-' + field.id;
63062             });
63063
63064         var label = enter
63065             .append('label')
63066             .attr('class', 'form-label')
63067             .attr('for', function(field) { return 'preset-input-' + field.id; })
63068             .text(function(field) { return field.label(); });
63069
63070         var wrap = label
63071             .append('div')
63072             .attr('class', 'form-label-button-wrap');
63073
63074         wrap.append('button')
63075             .attr('class', 'remove-icon')
63076             .attr('tabindex', -1)
63077             .call(svgIcon('#operation-delete'));
63078
63079         wrap.append('button')
63080             .attr('class', 'modified-icon')
63081             .attr('tabindex', -1)
63082             .call(
63083                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
63084             );
63085
63086
63087         // Update
63088         fields = fields
63089             .merge(enter);
63090
63091         fields.selectAll('.form-label-button-wrap .remove-icon')
63092             .on('click', remove);
63093
63094         fields.selectAll('.modified-icon')
63095             .on('click', revert);
63096
63097         fields
63098             .order()
63099             .classed('modified', function(field) { return field.modified(); })
63100             .classed('present', function(field) { return field.present(); })
63101             .each(function(field) {
63102                 var reference = uiTagReference(field.reference || { key: field.key }, context);
63103
63104                 if (state === 'hover') {
63105                     reference.showing(false);
63106                 }
63107
63108                 select(this)
63109                     .call(field.input)
63110                     .selectAll('input')
63111                     .on('keydown', function() {
63112                         // if user presses enter, and combobox is not active, accept edits..
63113                         if (event.keyCode === 13 && select('.combobox').empty()) {
63114                             context.enter(modeBrowse$$1(context));
63115                         }
63116                     })
63117                     .call(reference.body)
63118                     .select('.form-label-button-wrap')
63119                     .call(reference.button);
63120
63121                 field.input.tags(tags);
63122             });
63123
63124         notShown = notShown.map(function(field) {
63125             return {
63126                 title: field.label(),
63127                 value: field.label(),
63128                 field: field
63129             };
63130         });
63131
63132
63133         var more = selection$$1.selectAll('.more-fields')
63134             .data((notShown.length > 0) ? [0] : []);
63135
63136         more.exit()
63137             .remove();
63138
63139         more = more.enter()
63140             .append('div')
63141             .attr('class', 'more-fields')
63142             .append('label')
63143             .text(t('inspector.add_fields'))
63144             .merge(more);
63145
63146
63147         var input = more.selectAll('.value')
63148             .data([0]);
63149
63150         input.exit()
63151             .remove();
63152
63153         input = input.enter()
63154             .append('input')
63155             .attr('class', 'value')
63156             .attr('type', 'text')
63157             .merge(input);
63158
63159         input
63160             .call(utilGetSetValue, '')
63161             .attr('placeholder', function() {
63162                 var placeholder = [];
63163                 for (var field in notShown) {
63164                     placeholder.push(notShown[field].title);
63165                 }
63166                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
63167             })
63168             .call(d3combobox().data(notShown)
63169                 .minItems(1)
63170                 .on('accept', show));
63171
63172
63173         function show(field) {
63174             field = field.field;
63175             field.show = true;
63176             content(selection$$1);
63177             field.input.focus();
63178         }
63179
63180
63181         function revert(field) {
63182             event.stopPropagation();
63183             event.preventDefault();
63184             dispatch$$1.call('change', field, field.revert());
63185         }
63186
63187
63188         function remove(field) {
63189             event.stopPropagation();
63190             event.preventDefault();
63191             dispatch$$1.call('change', field, field.remove());
63192         }
63193     }
63194
63195
63196     presets.preset = function(_) {
63197         if (!arguments.length) return preset;
63198         if (preset && preset.id === _.id) return presets;
63199         preset = _;
63200         fieldsArr = null;
63201         return presets;
63202     };
63203
63204
63205     presets.state = function(_) {
63206         if (!arguments.length) return state;
63207         state = _;
63208         return presets;
63209     };
63210
63211
63212     presets.tags = function(_) {
63213         if (!arguments.length) return tags;
63214         tags = _;
63215         // Don't reset fieldsArr here.
63216         return presets;
63217     };
63218
63219
63220     presets.entityID = function(_) {
63221         if (!arguments.length) return id;
63222         if (id === _) return presets;
63223         id = _;
63224         fieldsArr = null;
63225         return presets;
63226     };
63227
63228
63229     return utilRebind(presets, dispatch$$1, 'on');
63230 }
63231
63232 function uiEntityEditor(context) {
63233     var dispatch$$1 = dispatch('choose'),
63234         state = 'select',
63235         coalesceChanges = false,
63236         modified = false,
63237         base,
63238         id,
63239         activePreset,
63240         reference;
63241
63242     var presetEditor = uiPreset(context)
63243         .on('change', changeTags);
63244     var rawTagEditor = uiRawTagEditor(context)
63245         .on('change', changeTags);
63246
63247
63248     function entityEditor(selection$$1) {
63249         var entity = context.entity(id),
63250             tags = lodash.clone(entity.tags);
63251
63252         // Header
63253         var header = selection$$1.selectAll('.header')
63254             .data([0]);
63255
63256         // Enter
63257         var enter = header.enter()
63258             .append('div')
63259             .attr('class', 'header fillL cf');
63260
63261         enter
63262             .append('button')
63263             .attr('class', 'fl preset-reset preset-choose')
63264             .append('span')
63265             .html((textDirection === 'rtl') ? '&#9658;' : '&#9668;');
63266
63267         enter
63268             .append('button')
63269             .attr('class', 'fr preset-close')
63270             .on('click', function() { context.enter(modeBrowse$$1(context)); })
63271             .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
63272
63273         enter
63274             .append('h3')
63275             .text(t('inspector.edit'));
63276
63277         // Update
63278         header = header
63279             .merge(enter);
63280
63281         header.selectAll('.preset-reset')
63282             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
63283
63284
63285         // Body
63286         var body = selection$$1.selectAll('.inspector-body')
63287             .data([0]);
63288
63289         // Enter
63290         enter = body.enter()
63291             .append('div')
63292             .attr('class', 'inspector-body');
63293
63294         enter
63295             .append('div')
63296             .attr('class', 'preset-list-item inspector-inner')
63297             .append('div')
63298             .attr('class', 'preset-list-button-wrap')
63299             .append('button')
63300             .attr('class', 'preset-list-button preset-reset')
63301             .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
63302             .append('div')
63303             .attr('class', 'label');
63304
63305         enter
63306             .append('div')
63307             .attr('class', 'inspector-border inspector-preset');
63308
63309         enter
63310             .append('div')
63311             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
63312
63313         enter
63314             .append('div')
63315             .attr('class', 'inspector-border raw-member-editor inspector-inner');
63316
63317         enter
63318             .append('div')
63319             .attr('class', 'raw-membership-editor inspector-inner');
63320
63321         // Update
63322         body = body
63323             .merge(enter);
63324
63325         body.selectAll('.preset-list-button-wrap')
63326             .call(reference.button);
63327
63328         body.selectAll('.preset-list-item')
63329             .call(reference.body);
63330
63331         body.selectAll('.preset-reset')
63332             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
63333
63334         body.select('.preset-list-item button')
63335             .call(uiPresetIcon()
63336                 .geometry(context.geometry(id))
63337                 .preset(activePreset));
63338
63339         body.select('.preset-list-item .label')
63340             .text(activePreset.name());
63341
63342         body.select('.inspector-preset')
63343             .call(presetEditor
63344                 .preset(activePreset)
63345                 .entityID(id)
63346                 .tags(tags)
63347                 .state(state));
63348
63349         body.select('.raw-tag-editor')
63350             .call(rawTagEditor
63351                 .preset(activePreset)
63352                 .entityID(id)
63353                 .tags(tags)
63354                 .state(state));
63355
63356         if (entity.type === 'relation') {
63357             body.select('.raw-member-editor')
63358                 .style('display', 'block')
63359                 .call(uiRawMemberEditor(context)
63360                     .entityID(id));
63361         } else {
63362             body.select('.raw-member-editor')
63363                 .style('display', 'none');
63364         }
63365
63366         body.select('.raw-membership-editor')
63367             .call(uiRawMembershipEditor(context)
63368                 .entityID(id));
63369
63370
63371         context.history()
63372             .on('change.entity-editor', historyChanged);
63373
63374
63375         function historyChanged() {
63376             if (state === 'hide') return;
63377
63378             var entity = context.hasEntity(id),
63379                 graph = context.graph();
63380             if (!entity) return;
63381
63382             entityEditor.preset(context.presets().match(entity, graph));
63383             entityEditor.modified(base !== graph);
63384             entityEditor(selection$$1);
63385         }
63386     }
63387
63388
63389     function clean(o) {
63390
63391         function cleanVal(k, v) {
63392             function keepSpaces(k) {
63393                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
63394                     'operating_times', 'smoking_hours', 'happy_hours'];
63395                 return lodash.some(whitelist, function(s) { return k.indexOf(s) !== -1; });
63396             }
63397
63398             var blacklist = ['description', 'note', 'fixme'];
63399             if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
63400
63401             var cleaned = v.split(';')
63402                 .map(function(s) { return s.trim(); })
63403                 .join(keepSpaces(k) ? '; ' : ';');
63404
63405             // The code below is not intended to validate websites and emails.
63406             // It is only intended to prevent obvious copy-paste errors. (#2323)
63407
63408             // clean website- and email-like tags
63409             if (k.indexOf('website') !== -1 ||
63410                 k.indexOf('email') !== -1 ||
63411                 cleaned.indexOf('http') === 0) {
63412                 cleaned = cleaned
63413                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
63414
63415             }
63416
63417             return cleaned;
63418         }
63419
63420         var out = {}, k, v;
63421         for (k in o) {
63422             if (k && (v = o[k]) !== undefined) {
63423                 out[k] = cleanVal(k, v);
63424             }
63425         }
63426         return out;
63427     }
63428
63429
63430     // Tag changes that fire on input can all get coalesced into a single
63431     // history operation when the user leaves the field.  #2342
63432     function changeTags(changed, onInput) {
63433         var entity = context.entity(id),
63434             annotation = t('operations.change_tags.annotation'),
63435             tags = lodash.clone(entity.tags);
63436
63437         lodash.forEach(changed, function(v, k) {
63438             if (v !== undefined || tags.hasOwnProperty(k)) {
63439                 tags[k] = v;
63440             }
63441         });
63442
63443         if (!onInput) {
63444             tags = clean(tags);
63445         }
63446
63447         if (!lodash.isEqual(entity.tags, tags)) {
63448             if (coalesceChanges) {
63449                 context.overwrite(actionChangeTags(id, tags), annotation);
63450             } else {
63451                 context.perform(actionChangeTags(id, tags), annotation);
63452                 coalesceChanges = !!onInput;
63453             }
63454         }
63455     }
63456
63457
63458     entityEditor.modified = function(_) {
63459         if (!arguments.length) return modified;
63460         modified = _;
63461         selectAll('button.preset-close use')
63462             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
63463     };
63464
63465
63466     entityEditor.state = function(_) {
63467         if (!arguments.length) return state;
63468         state = _;
63469         return entityEditor;
63470     };
63471
63472
63473     entityEditor.entityID = function(_) {
63474         if (!arguments.length) return id;
63475         id = _;
63476         base = context.graph();
63477         entityEditor.preset(context.presets().match(context.entity(id), base));
63478         entityEditor.modified(false);
63479         coalesceChanges = false;
63480         return entityEditor;
63481     };
63482
63483
63484     entityEditor.preset = function(_) {
63485         if (!arguments.length) return activePreset;
63486         if (_ !== activePreset) {
63487             activePreset = _;
63488             reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
63489                 .showing(false);
63490         }
63491         return entityEditor;
63492     };
63493
63494
63495     return utilRebind(entityEditor, dispatch$$1, 'on');
63496 }
63497
63498 function uiPresetList(context) {
63499     var dispatch$$1 = dispatch('choose'),
63500         id,
63501         currentPreset,
63502         autofocus = false;
63503
63504
63505     function presetList(selection$$1) {
63506         var entity = context.entity(id),
63507             geometry = context.geometry(id);
63508
63509         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
63510         if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
63511             geometry = 'point';
63512         }
63513
63514         var presets = context.presets().matchGeometry(geometry);
63515
63516         selection$$1.html('');
63517
63518         var messagewrap = selection$$1
63519             .append('div')
63520             .attr('class', 'header fillL cf');
63521
63522         var message = messagewrap
63523             .append('h3')
63524             .text(t('inspector.choose'));
63525
63526         if (context.entity(id).isUsed(context.graph())) {
63527             messagewrap
63528                 .append('button')
63529                 .attr('class', 'preset-choose')
63530                 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
63531                 .append('span')
63532                 .html((textDirection === 'rtl') ? '&#9668;' : '&#9658;');
63533         } else {
63534             messagewrap
63535                 .append('button')
63536                 .attr('class', 'close')
63537                 .on('click', function() {
63538                     context.enter(modeBrowse$$1(context));
63539                 })
63540                 .call(svgIcon('#icon-close'));
63541         }
63542
63543         function keydown() {
63544             // hack to let delete shortcut work when search is autofocused
63545             if (search.property('value').length === 0 &&
63546                 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
63547                  event.keyCode === d3keybinding.keyCodes['⌦'])) {
63548                 event.preventDefault();
63549                 event.stopPropagation();
63550                 operationDelete([id], context)();
63551             } else if (search.property('value').length === 0 &&
63552                 (event.ctrlKey || event.metaKey) &&
63553                 event.keyCode === d3keybinding.keyCodes.z) {
63554                 event.preventDefault();
63555                 event.stopPropagation();
63556                 context.undo();
63557             } else if (!event.ctrlKey && !event.metaKey) {
63558                 select(this).on('keydown', null);
63559             }
63560         }
63561
63562         function keypress() {
63563             // enter
63564             var value = search.property('value');
63565             if (event.keyCode === 13 && value.length) {
63566                 list.selectAll('.preset-list-item:first-child').datum().choose();
63567             }
63568         }
63569
63570         function inputevent() {
63571             var value = search.property('value');
63572             list.classed('filtered', value.length);
63573             if (value.length) {
63574                 var results = presets.search(value, geometry);
63575                 message.text(t('inspector.results', {
63576                     n: results.collection.length,
63577                     search: value
63578                 }));
63579                 list.call(drawList, results);
63580             } else {
63581                 list.call(drawList, context.presets().defaults(geometry, 36));
63582                 message.text(t('inspector.choose'));
63583             }
63584         }
63585
63586         var searchWrap = selection$$1
63587             .append('div')
63588             .attr('class', 'search-header');
63589
63590         var search = searchWrap
63591             .append('input')
63592             .attr('class', 'preset-search-input')
63593             .attr('placeholder', t('inspector.search'))
63594             .attr('type', 'search')
63595             .on('keydown', keydown)
63596             .on('keypress', keypress)
63597             .on('input', inputevent);
63598
63599         searchWrap
63600             .call(svgIcon('#icon-search', 'pre-text'));
63601
63602         if (autofocus) {
63603             search.node().focus();
63604         }
63605
63606         var listWrap = selection$$1
63607             .append('div')
63608             .attr('class', 'inspector-body');
63609
63610         var list = listWrap
63611             .append('div')
63612             .attr('class', 'preset-list fillL cf')
63613             .call(drawList, context.presets().defaults(geometry, 36));
63614     }
63615
63616
63617     function drawList(list, presets) {
63618         var collection = presets.collection.map(function(preset) {
63619             return preset.members ? CategoryItem(preset) : PresetItem(preset);
63620         });
63621
63622         var items = list.selectAll('.preset-list-item')
63623             .data(collection, function(d) { return d.preset.id; });
63624
63625         items.order();
63626
63627         items.exit()
63628             .remove();
63629
63630         items.enter()
63631             .append('div')
63632             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
63633             .classed('current', function(item) { return item.preset === currentPreset; })
63634             .each(function(item) { select(this).call(item); })
63635             .style('opacity', 0)
63636             .transition()
63637             .style('opacity', 1);
63638     }
63639
63640
63641     function CategoryItem(preset) {
63642         var box, sublist, shown = false;
63643
63644         function item(selection$$1) {
63645             var wrap = selection$$1.append('div')
63646                 .attr('class', 'preset-list-button-wrap category col12');
63647
63648             wrap.append('button')
63649                 .attr('class', 'preset-list-button')
63650                 .classed('expanded', false)
63651                 .call(uiPresetIcon()
63652                     .geometry(context.geometry(id))
63653                     .preset(preset))
63654                 .on('click', function() {
63655                     var isExpanded = select(this).classed('expanded');
63656                     var triangle = isExpanded ? '▶ ' :  '▼ ';
63657                     select(this).classed('expanded', !isExpanded);
63658                     select(this).selectAll('.label').text(triangle + preset.name());
63659                     item.choose();
63660                 })
63661                 .append('div')
63662                 .attr('class', 'label')
63663                 .text(function() {
63664                   return '▶ ' + preset.name();
63665                 });
63666
63667             box = selection$$1.append('div')
63668                 .attr('class', 'subgrid col12')
63669                 .style('max-height', '0px')
63670                 .style('opacity', 0);
63671
63672             box.append('div')
63673                 .attr('class', 'arrow');
63674
63675             sublist = box.append('div')
63676                 .attr('class', 'preset-list fillL3 cf fl');
63677         }
63678
63679         item.choose = function() {
63680             if (!box || !sublist) return;
63681
63682             if (shown) {
63683                 shown = false;
63684                 box.transition()
63685                     .duration(200)
63686                     .style('opacity', '0')
63687                     .style('max-height', '0px')
63688                     .style('padding-bottom', '0px');
63689             } else {
63690                 shown = true;
63691                 sublist.call(drawList, preset.members);
63692                 box.transition()
63693                     .duration(200)
63694                     .style('opacity', '1')
63695                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
63696                     .style('padding-bottom', '20px');
63697             }
63698         };
63699
63700         item.preset = preset;
63701
63702         return item;
63703     }
63704
63705
63706     function PresetItem(preset) {
63707         function item(selection$$1) {
63708             var wrap = selection$$1.append('div')
63709                 .attr('class', 'preset-list-button-wrap col12');
63710
63711             wrap.append('button')
63712                 .attr('class', 'preset-list-button')
63713                 .call(uiPresetIcon()
63714                     .geometry(context.geometry(id))
63715                     .preset(preset))
63716                 .on('click', item.choose)
63717                 .append('div')
63718                 .attr('class', 'label')
63719                 .text(preset.name());
63720
63721             wrap.call(item.reference.button);
63722             selection$$1.call(item.reference.body);
63723         }
63724
63725         item.choose = function() {
63726             context.presets().choose(preset);
63727
63728             context.perform(
63729                 actionChangePreset(id, currentPreset, preset),
63730                 t('operations.change_tags.annotation')
63731             );
63732
63733             dispatch$$1.call('choose', this, preset);
63734         };
63735
63736         item.help = function() {
63737             event.stopPropagation();
63738             item.reference.toggle();
63739         };
63740
63741         item.preset = preset;
63742         item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
63743
63744         return item;
63745     }
63746
63747
63748     presetList.autofocus = function(_) {
63749         if (!arguments.length) return autofocus;
63750         autofocus = _;
63751         return presetList;
63752     };
63753
63754
63755     presetList.entityID = function(_) {
63756         if (!arguments.length) return id;
63757         id = _;
63758         presetList.preset(context.presets().match(context.entity(id), context.graph()));
63759         return presetList;
63760     };
63761
63762
63763     presetList.preset = function(_) {
63764         if (!arguments.length) return currentPreset;
63765         currentPreset = _;
63766         return presetList;
63767     };
63768
63769
63770     return utilRebind(presetList, dispatch$$1, 'on');
63771 }
63772
63773 function uiViewOnOSM(context) {
63774     var id;
63775
63776     function viewOnOSM(selection) {
63777         var entity = context.entity(id);
63778
63779         selection.style('display', entity.isNew() ? 'none' : null);
63780
63781         var link = selection.selectAll('.view-on-osm')
63782             .data([0]);
63783
63784         link.enter()
63785             .append('a')
63786             .attr('class', 'view-on-osm')
63787             .attr('target', '_blank')
63788             .call(svgIcon('#icon-out-link', 'inline'))
63789             .append('span')
63790             .text(t('inspector.view_on_osm'));
63791
63792         link
63793             .attr('href', context.connection().entityURL(entity));
63794     }
63795
63796
63797     viewOnOSM.entityID = function(_) {
63798         if (!arguments.length) return id;
63799         id = _;
63800         return viewOnOSM;
63801     };
63802
63803     return viewOnOSM;
63804 }
63805
63806 function uiInspector(context) {
63807     var presetList = uiPresetList(context),
63808         entityEditor = uiEntityEditor(context),
63809         state = 'select',
63810         entityID,
63811         newFeature = false;
63812
63813
63814     function inspector(selection$$1) {
63815         presetList
63816             .entityID(entityID)
63817             .autofocus(newFeature)
63818             .on('choose', setPreset);
63819
63820         entityEditor
63821             .state(state)
63822             .entityID(entityID)
63823             .on('choose', showList);
63824
63825         var wrap = selection$$1.selectAll('.panewrap')
63826             .data([0]);
63827
63828         var enter = wrap.enter()
63829             .append('div')
63830             .attr('class', 'panewrap');
63831
63832         enter
63833             .append('div')
63834             .attr('class', 'preset-list-pane pane');
63835
63836         enter
63837             .append('div')
63838             .attr('class', 'entity-editor-pane pane');
63839
63840         wrap = wrap.merge(enter);
63841         var presetPane = wrap.selectAll('.preset-list-pane');
63842         var editorPane = wrap.selectAll('.entity-editor-pane');
63843
63844         var graph = context.graph(),
63845             entity = context.entity(entityID),
63846             showEditor = state === 'hover' ||
63847                 entity.isUsed(graph) ||
63848                 entity.isHighwayIntersection(graph);
63849
63850         if (showEditor) {
63851             wrap.style('right', '0%');
63852             editorPane.call(entityEditor);
63853         } else {
63854             wrap.style('right', '-100%');
63855             presetPane.call(presetList);
63856         }
63857
63858         var footer = selection$$1.selectAll('.footer')
63859             .data([0]);
63860
63861         footer = footer.enter()
63862             .append('div')
63863             .attr('class', 'footer')
63864             .merge(footer);
63865
63866         footer
63867             .call(uiViewOnOSM(context).entityID(entityID));
63868
63869
63870         function showList(preset) {
63871             wrap.transition()
63872                 .styleTween('right', function() { return interpolate('0%', '-100%'); });
63873
63874             presetPane
63875                 .call(presetList.preset(preset).autofocus(true));
63876         }
63877
63878
63879         function setPreset(preset) {
63880             wrap.transition()
63881                 .styleTween('right', function() { return interpolate('-100%', '0%'); });
63882
63883             editorPane
63884                 .call(entityEditor.preset(preset));
63885         }
63886     }
63887
63888
63889     inspector.state = function(_) {
63890         if (!arguments.length) return state;
63891         state = _;
63892         entityEditor.state(state);
63893         return inspector;
63894     };
63895
63896
63897     inspector.entityID = function(_) {
63898         if (!arguments.length) return entityID;
63899         entityID = _;
63900         return inspector;
63901     };
63902
63903
63904     inspector.newFeature = function(_) {
63905         if (!arguments.length) return newFeature;
63906         newFeature = _;
63907         return inspector;
63908     };
63909
63910
63911     return inspector;
63912 }
63913
63914 function uiNotice(context) {
63915
63916     return function(selection) {
63917         var div = selection
63918             .append('div')
63919             .attr('class', 'notice');
63920
63921         var button = div
63922             .append('button')
63923             .attr('class', 'zoom-to notice')
63924             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
63925
63926         button
63927             .call(svgIcon('#icon-plus', 'pre-text'))
63928             .append('span')
63929             .attr('class', 'label')
63930             .text(t('zoom_in_edit'));
63931
63932
63933         function disableTooHigh() {
63934             div.style('display', context.editable() ? 'none' : 'block');
63935         }
63936
63937         context.map()
63938             .on('move.notice', lodash.debounce(disableTooHigh, 500));
63939
63940         disableTooHigh();
63941     };
63942 }
63943
63944 function uiSidebar(context) {
63945     var inspector = uiInspector(context),
63946         current;
63947
63948
63949     function sidebar(selection) {
63950         var featureListWrap = selection
63951             .append('div')
63952             .attr('class', 'feature-list-pane')
63953             .call(uiFeatureList(context));
63954
63955         selection
63956             .call(uiNotice(context));
63957
63958         var inspectorWrap = selection
63959             .append('div')
63960             .attr('class', 'inspector-hidden inspector-wrap fr');
63961
63962
63963         function hover(id) {
63964             if (!current && context.hasEntity(id)) {
63965                 featureListWrap
63966                     .classed('inspector-hidden', true);
63967
63968                 inspectorWrap
63969                     .classed('inspector-hidden', false)
63970                     .classed('inspector-hover', true);
63971
63972                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
63973                     inspector
63974                         .state('hover')
63975                         .entityID(id);
63976
63977                     inspectorWrap
63978                         .call(inspector);
63979                 }
63980
63981             } else if (!current) {
63982                 featureListWrap
63983                     .classed('inspector-hidden', false);
63984                 inspectorWrap
63985                     .classed('inspector-hidden', true);
63986                 inspector
63987                     .state('hide');
63988             }
63989         }
63990
63991
63992         sidebar.hover = lodash.throttle(hover, 200);
63993
63994
63995         sidebar.select = function(id, newFeature) {
63996             if (!current && id) {
63997                 featureListWrap
63998                     .classed('inspector-hidden', true);
63999
64000                 inspectorWrap
64001                     .classed('inspector-hidden', false)
64002                     .classed('inspector-hover', false);
64003
64004                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
64005                     inspector
64006                         .state('select')
64007                         .entityID(id)
64008                         .newFeature(newFeature);
64009
64010                     inspectorWrap
64011                         .call(inspector);
64012                 }
64013
64014             } else if (!current) {
64015                 featureListWrap
64016                     .classed('inspector-hidden', false);
64017                 inspectorWrap
64018                     .classed('inspector-hidden', true);
64019                 inspector
64020                     .state('hide');
64021             }
64022         };
64023
64024
64025         sidebar.show = function(component) {
64026             featureListWrap
64027                 .classed('inspector-hidden', true);
64028             inspectorWrap
64029                 .classed('inspector-hidden', true);
64030
64031             if (current) current.remove();
64032             current = selection
64033                 .append('div')
64034                 .attr('class', 'sidebar-component')
64035                 .call(component);
64036         };
64037
64038
64039         sidebar.hide = function() {
64040             featureListWrap
64041                 .classed('inspector-hidden', false);
64042             inspectorWrap
64043                 .classed('inspector-hidden', true);
64044
64045             if (current) current.remove();
64046             current = null;
64047         };
64048     }
64049
64050
64051     sidebar.hover = function() {};
64052     sidebar.hover.cancel = function() {};
64053     sidebar.select = function() {};
64054     sidebar.show = function() {};
64055     sidebar.hide = function() {};
64056
64057     return sidebar;
64058 }
64059
64060 function uiSpinner(context) {
64061     var connection = context.connection();
64062
64063
64064     return function(selection) {
64065         var img = selection
64066             .append('img')
64067             .attr('src', context.imagePath('loader-black.gif'))
64068             .style('opacity', 0);
64069
64070         connection
64071             .on('loading.spinner', function() {
64072                 img.transition()
64073                     .style('opacity', 1);
64074             });
64075
64076         connection
64077             .on('loaded.spinner', function() {
64078                 img.transition()
64079                     .style('opacity', 0);
64080             });
64081     };
64082 }
64083
64084 function uiSplash(context) {
64085
64086     return function(selection$$1) {
64087         if (context.storage('sawSplash'))
64088              return;
64089
64090         context.storage('sawSplash', true);
64091
64092         var modalSelection = uiModal(selection$$1);
64093
64094         modalSelection.select('.modal')
64095             .attr('class', 'modal-splash modal col6');
64096
64097         var introModal = modalSelection.select('.content')
64098             .append('div')
64099             .attr('class', 'fillL');
64100
64101         introModal
64102             .append('div')
64103             .attr('class','modal-section cf')
64104             .append('h3').text(t('splash.welcome'));
64105
64106         introModal
64107             .append('div')
64108             .attr('class','modal-section')
64109             .append('p')
64110             .html(t('splash.text', {
64111                 version: context.version,
64112                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
64113                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
64114             }));
64115
64116         var buttons = introModal
64117             .append('div')
64118             .attr('class', 'modal-actions cf');
64119
64120         buttons
64121             .append('button')
64122             .attr('class', 'col6 walkthrough')
64123             .text(t('splash.walkthrough'))
64124             .on('click', function() {
64125                 select(document.body).call(uiIntro(context));
64126                 modalSelection.close();
64127             });
64128
64129         buttons
64130             .append('button')
64131             .attr('class', 'col6 start')
64132             .text(t('splash.start'))
64133             .on('click', modalSelection.close);
64134
64135         modalSelection.select('button.close')
64136             .attr('class','hide');
64137
64138     };
64139 }
64140
64141 function uiStatus(context) {
64142     var connection = context.connection();
64143
64144     return function(selection$$1) {
64145
64146         function update() {
64147             connection.status(function(err, apiStatus) {
64148                 selection$$1.html('');
64149
64150                 if (err) {
64151                     if (apiStatus === 'rateLimited') {
64152                         selection$$1
64153                             .text(t('status.rateLimit'))
64154                             .append('a')
64155                             .attr('class', 'api-status-login')
64156                             .attr('target', '_blank')
64157                             .call(svgIcon('#icon-out-link', 'inline'))
64158                             .append('span')
64159                             .text(t('login'))
64160                             .on('click.login', function() {
64161                                 event.preventDefault();
64162                                 connection.authenticate();
64163                             });
64164                     } else {
64165                         // TODO: nice messages for different error types
64166                         selection$$1.text(t('status.error'));
64167                     }
64168
64169                 } else if (apiStatus === 'readonly') {
64170                     selection$$1.text(t('status.readonly'));
64171                 } else if (apiStatus === 'offline') {
64172                     selection$$1.text(t('status.offline'));
64173                 }
64174
64175                 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
64176             });
64177         }
64178
64179         connection
64180             .on('change', function() { update(selection$$1); });
64181
64182         window.setInterval(update, 90000);
64183         update(selection$$1);
64184     };
64185 }
64186
64187 function uiUndoRedo(context) {
64188     var commands = [{
64189         id: 'undo',
64190         cmd: uiCmd('⌘Z'),
64191         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
64192         annotation: function() { return context.history().undoAnnotation(); }
64193     }, {
64194         id: 'redo',
64195         cmd: uiCmd('⌘⇧Z'),
64196         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
64197         annotation: function() { return context.history().redoAnnotation(); }
64198     }];
64199
64200
64201     function saving() {
64202         return context.mode().id === 'save';
64203     }
64204
64205
64206     return function(selection$$1) {
64207         var tooltipBehavior = tooltip()
64208             .placement('bottom')
64209             .html(true)
64210             .title(function (d) {
64211                 return uiTooltipHtml(d.annotation() ?
64212                     t(d.id + '.tooltip', {action: d.annotation()}) :
64213                     t(d.id + '.nothing'), d.cmd);
64214             });
64215
64216         var buttons = selection$$1.selectAll('button')
64217             .data(commands)
64218             .enter()
64219             .append('button')
64220             .attr('class', 'col6 disabled')
64221             .on('click', function(d) { return d.action(); })
64222             .call(tooltipBehavior);
64223
64224         buttons.each(function(d) {
64225             var iconName = d.id;
64226             if (textDirection === 'rtl') {
64227                 if (iconName === 'undo') {
64228                     iconName = 'redo';
64229                 } else if (iconName === 'redo') {
64230                     iconName = 'undo';
64231                 }
64232             }
64233             select(this)
64234                 .call(svgIcon('#icon-' + iconName));
64235         });
64236
64237         var keybinding = d3keybinding('undo')
64238             .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
64239             .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
64240
64241         select(document)
64242             .call(keybinding);
64243
64244         context.history()
64245             .on('change.undo_redo', update);
64246
64247         context
64248             .on('enter.undo_redo', update);
64249
64250         function update() {
64251             buttons
64252                 .property('disabled', saving())
64253                 .classed('disabled', function(d) { return !d.annotation(); })
64254                 .each(function() {
64255                     var selection$$1 = select(this);
64256                     if (selection$$1.property('tooltipVisible')) {
64257                         selection$$1.call(tooltipBehavior.show);
64258                     }
64259                 });
64260         }
64261     };
64262 }
64263
64264 function uiZoom(context) {
64265     var zooms = [{
64266         id: 'zoom-in',
64267         icon: 'plus',
64268         title: t('zoom.in'),
64269         action: context.zoomIn,
64270         key: '+'
64271     }, {
64272         id: 'zoom-out',
64273         icon: 'minus',
64274         title: t('zoom.out'),
64275         action: context.zoomOut,
64276         key: '-'
64277     }];
64278
64279
64280     function zoomIn() {
64281         event.preventDefault();
64282         if (!context.inIntro()) context.zoomIn();
64283     }
64284
64285
64286     function zoomOut() {
64287         event.preventDefault();
64288         if (!context.inIntro()) context.zoomOut();
64289     }
64290
64291
64292     function zoomInFurther() {
64293         event.preventDefault();
64294         if (!context.inIntro()) context.zoomInFurther();
64295     }
64296
64297
64298     function zoomOutFurther() {
64299         event.preventDefault();
64300         if (!context.inIntro()) context.zoomOutFurther();
64301     }
64302
64303
64304     return function(selection$$1) {
64305         var button = selection$$1.selectAll('button')
64306             .data(zooms)
64307             .enter()
64308             .append('button')
64309             .attr('tabindex', -1)
64310             .attr('class', function(d) { return d.id; })
64311             .on('click.editor', function(d) { d.action(); })
64312             .call(tooltip()
64313                 .placement((textDirection === 'rtl') ? 'right' : 'left')
64314                 .html(true)
64315                 .title(function(d) {
64316                     return uiTooltipHtml(d.title, d.key);
64317                 })
64318             );
64319
64320         button.each(function(d) {
64321             select(this)
64322                 .call(svgIcon('#icon-' + d.icon, 'light'));
64323         });
64324
64325         var keybinding = d3keybinding('zoom');
64326
64327         lodash.each(['=','ffequals','plus','ffplus'], function(key) {
64328             keybinding.on([key, '⇧' + key], zoomIn);
64329             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
64330         });
64331         lodash.each(['-','ffminus','dash'], function(key) {
64332             keybinding.on([key, '⇧' + key], zoomOut);
64333             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
64334         });
64335
64336         select(document)
64337             .call(keybinding);
64338     };
64339 }
64340
64341 function uiInit(context) {
64342
64343     function render(container) {
64344         var map$$1 = context.map();
64345
64346         var hash = behaviorHash(context);
64347         hash();
64348
64349         if (!hash.hadHash) {
64350             map$$1.centerZoom([0, 0], 2);
64351         }
64352
64353         container
64354             .append('svg')
64355             .attr('id', 'defs')
64356             .call(svgDefs(context));
64357
64358         container
64359             .append('div')
64360             .attr('id', 'sidebar')
64361             .attr('class', 'col4')
64362             .call(ui.sidebar);
64363
64364         var content = container
64365             .append('div')
64366             .attr('id', 'content');
64367
64368         var bar = content
64369             .append('div')
64370             .attr('id', 'bar')
64371             .attr('class', 'fillD');
64372
64373         content
64374             .append('div')
64375             .attr('id', 'map')
64376             .attr('dir', 'ltr')
64377             .call(map$$1);
64378
64379         if (textDirection === 'rtl') {
64380             select('body').attr('dir', 'rtl');
64381         }
64382
64383         content
64384             .call(uiMapInMap(context));
64385
64386         content
64387             .append('div')
64388             .call(uiInfo(context));
64389
64390         bar
64391             .append('div')
64392             .attr('class', 'spacer col4');
64393
64394         var limiter = bar.append('div')
64395             .attr('class', 'limiter');
64396
64397         limiter
64398             .append('div')
64399             .attr('class', 'button-wrap joined col3')
64400             .call(uiModes(context), limiter);
64401
64402         limiter
64403             .append('div')
64404             .attr('class', 'button-wrap joined col1')
64405             .call(uiUndoRedo(context));
64406
64407         limiter
64408             .append('div')
64409             .attr('class', 'button-wrap col1')
64410             .call(uiSave(context));
64411
64412         bar
64413             .append('div')
64414             .attr('class', 'full-screen')
64415             .call(uiFullScreen(context));
64416
64417         bar
64418             .append('div')
64419             .attr('class', 'spinner')
64420             .call(uiSpinner(context));
64421
64422         var controls = bar
64423             .append('div')
64424             .attr('class', 'map-controls');
64425
64426         controls
64427             .append('div')
64428             .attr('class', 'map-control zoombuttons')
64429             .call(uiZoom(context));
64430
64431         controls
64432             .append('div')
64433             .attr('class', 'map-control geolocate-control')
64434             .call(uiGeolocate(context));
64435
64436         controls
64437             .append('div')
64438             .attr('class', 'map-control background-control')
64439             .call(uiBackground(context));
64440
64441         controls
64442             .append('div')
64443             .attr('class', 'map-control map-data-control')
64444             .call(uiMapData(context));
64445
64446         controls
64447             .append('div')
64448             .attr('class', 'map-control help-control')
64449             .call(uiHelp(context));
64450
64451         var about = content
64452             .append('div')
64453             .attr('id', 'about');
64454
64455         about
64456             .append('div')
64457             .attr('id', 'attrib')
64458             .attr('dir', 'ltr')
64459             .call(uiAttribution(context));
64460
64461         var footer = about
64462             .append('div')
64463             .attr('id', 'footer')
64464             .attr('class', 'fillD');
64465
64466         footer
64467             .append('div')
64468             .attr('class', 'api-status')
64469             .call(uiStatus(context));
64470
64471         footer
64472             .append('div')
64473             .attr('id', 'scale-block')
64474             .call(uiScale(context));
64475
64476         var aboutList = footer
64477             .append('div')
64478             .attr('id', 'info-block')
64479             .append('ul')
64480             .attr('id', 'about-list');
64481
64482         if (!context.embed()) {
64483             aboutList.call(uiAccount(context));
64484         }
64485
64486         aboutList
64487             .append('li')
64488             .append('a')
64489             .attr('target', '_blank')
64490             .attr('tabindex', -1)
64491             .attr('href', 'https://github.com/openstreetmap/iD')
64492             .text(context.version);
64493
64494         var issueLinks = aboutList
64495             .append('li');
64496
64497         issueLinks
64498             .append('a')
64499             .attr('target', '_blank')
64500             .attr('tabindex', -1)
64501             .attr('href', 'https://github.com/openstreetmap/iD/issues')
64502             .call(svgIcon('#icon-bug', 'light'))
64503             .call(tooltip().title(t('report_a_bug')).placement('top'));
64504
64505         issueLinks
64506             .append('a')
64507             .attr('target', '_blank')
64508             .attr('tabindex', -1)
64509             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
64510             .call(svgIcon('#icon-translate', 'light'))
64511             .call(tooltip().title(t('help_translate')).placement('top'));
64512
64513         aboutList
64514             .append('li')
64515             .attr('class', 'feature-warning')
64516             .attr('tabindex', -1)
64517             .call(uiFeatureInfo(context));
64518
64519         aboutList
64520             .append('li')
64521             .attr('class', 'user-list')
64522             .attr('tabindex', -1)
64523             .call(uiContributors(context));
64524
64525
64526         window.onbeforeunload = function() {
64527             return context.save();
64528         };
64529
64530         window.onunload = function() {
64531             context.history().unlock();
64532         };
64533
64534         var mapDimensions = map$$1.dimensions();
64535
64536         function onResize() {
64537             mapDimensions = utilGetDimensions(content, true);
64538             map$$1.dimensions(mapDimensions);
64539         }
64540
64541         select(window)
64542             .on('resize.editor', onResize);
64543
64544         onResize();
64545
64546         function pan(d) {
64547             return function() {
64548                 event.preventDefault();
64549                 if (!context.inIntro()) {
64550                     context.pan(d, 100);
64551                 }
64552             };
64553         }
64554
64555         // pan amount
64556         var pa = 10;
64557
64558         var keybinding = d3keybinding('main')
64559             .on('⌫', function() { event.preventDefault(); })
64560             .on('←', pan([pa, 0]))
64561             .on('↑', pan([0, pa]))
64562             .on('→', pan([-pa, 0]))
64563             .on('↓', pan([0, -pa]))
64564             .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
64565             .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
64566             .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
64567             .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
64568
64569         select(document)
64570             .call(keybinding);
64571
64572         context.enter(modeBrowse$$1(context));
64573
64574         context.container()
64575             .call(uiSplash(context))
64576             .call(uiRestore(context));
64577
64578         var authenticating = uiLoading(context)
64579             .message(t('loading_auth'))
64580             .blocking(true);
64581
64582         context.connection()
64583             .on('authLoading.ui', function() {
64584                 context.container()
64585                     .call(authenticating);
64586             })
64587             .on('authDone.ui', function() {
64588                 authenticating.close();
64589             });
64590     }
64591
64592
64593     function ui(node, callback) {
64594         var container = select(node);
64595         context.container(container);
64596         context.loadLocale(function(err) {
64597             if (!err) {
64598                 render(container);
64599             }
64600             if (callback) {
64601                 callback(err);
64602             }
64603         });
64604     }
64605
64606     ui.sidebar = uiSidebar(context);
64607
64608     return ui;
64609 }
64610
64611 function uiCommit(context) {
64612     var dispatch$$1 = dispatch('cancel', 'save');
64613
64614
64615     function commit(selection$$1) {
64616         var changes = context.history().changes(),
64617             summary = context.history().difference().summary();
64618
64619         selection$$1
64620             .append('div')
64621             .attr('class', 'header fillL')
64622             .append('h3')
64623             .text(t('commit.title'));
64624
64625         var body = selection$$1
64626             .append('div')
64627             .attr('class', 'body');
64628
64629         var commentSection = body
64630             .append('div')
64631             .attr('class', 'modal-section form-field commit-form');
64632
64633         commentSection
64634             .append('label')
64635             .attr('class', 'form-label')
64636             .text(t('commit.message_label'));
64637
64638         var commentField = commentSection
64639             .append('textarea')
64640             .attr('placeholder', t('commit.description_placeholder'))
64641             .attr('maxlength', 255)
64642             .property('value', context.storage('comment') || '')
64643             .on('input.save', checkComment)
64644             .on('change.save', checkComment)
64645             .on('blur.save', function() {
64646                 context.storage('comment', this.value);
64647             });
64648
64649
64650         commentField.node().select();
64651
64652         context.connection().userChangesets(function (err, changesets) {
64653             if (err) return;
64654
64655             var comments = [];
64656
64657             for (var i = 0; i < changesets.length; i++) {
64658                 if (changesets[i].tags.comment) {
64659                     comments.push({
64660                         title: changesets[i].tags.comment,
64661                         value: changesets[i].tags.comment
64662                     });
64663                 }
64664             }
64665
64666             commentField
64667                 .call(d3combobox().caseSensitive(true).data(comments));
64668         });
64669
64670         var clippyArea = commentSection.append('div')
64671             .attr('class', 'clippy-area');
64672
64673         var changeSetInfo = commentSection.append('div')
64674             .attr('class', 'changeset-info');
64675
64676         changeSetInfo.append('a')
64677             .attr('target', '_blank')
64678             .attr('tabindex', -1)
64679             .call(svgIcon('#icon-out-link', 'inline'))
64680             .attr('href', t('commit.about_changeset_comments_link'))
64681             .append('span')
64682             .text(t('commit.about_changeset_comments'));
64683
64684
64685         // Warnings
64686         var warnings = body.selectAll('div.warning-section')
64687             .data([context.history().validate(changes)]);
64688
64689         warnings = warnings.enter()
64690             .append('div')
64691             .attr('class', 'modal-section warning-section fillL2')
64692             .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
64693             .style('background', '#ffb')
64694             .merge(warnings);
64695
64696         warnings
64697             .append('h3')
64698             .text(t('commit.warnings'));
64699
64700         warnings
64701             .append('ul')
64702             .attr('class', 'changeset-list');
64703
64704         var warningLi = warnings.select('ul').selectAll('li')
64705             .data(function(d) { return d; });
64706
64707         warningLi = warningLi.enter()
64708             .append('li')
64709             .on('mouseover', mouseover)
64710             .on('mouseout', mouseout)
64711             .on('click', warningClick)
64712             .merge(warningLi);
64713
64714         warningLi
64715             .call(svgIcon('#icon-alert', 'pre-text'));
64716
64717         warningLi
64718             .append('strong')
64719             .text(function(d) { return d.message; });
64720
64721         warningLi.filter(function(d) { return d.tooltip; })
64722             .call(tooltip()
64723                 .title(function(d) { return d.tooltip; })
64724                 .placement('top')
64725             );
64726
64727
64728         // Upload Explanation
64729         var saveSection = body
64730             .append('div')
64731             .attr('class','modal-section save-section fillL cf');
64732
64733         var prose = saveSection
64734             .append('p')
64735             .attr('class', 'commit-info')
64736             .html(t('commit.upload_explanation'));
64737
64738
64739         context.connection().userDetails(function(err, user) {
64740             if (err) return;
64741
64742             var userLink = select(document.createElement('div'));
64743
64744             if (user.image_url) {
64745                 userLink
64746                     .append('img')
64747                     .attr('src', user.image_url)
64748                     .attr('class', 'icon pre-text user-icon');
64749             }
64750
64751             userLink
64752                 .append('a')
64753                 .attr('class','user-info')
64754                 .text(user.display_name)
64755                 .attr('href', context.connection().userURL(user.display_name))
64756                 .attr('tabindex', -1)
64757                 .attr('target', '_blank');
64758
64759             prose
64760                 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
64761         });
64762
64763
64764         // Buttons
64765         var buttonSection = saveSection
64766             .append('div')
64767             .attr('class','buttons fillL cf');
64768
64769         var cancelButton = buttonSection
64770             .append('button')
64771             .attr('class', 'secondary-action col5 button cancel-button')
64772             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
64773
64774         cancelButton
64775             .append('span')
64776             .attr('class', 'label')
64777             .text(t('commit.cancel'));
64778
64779         var saveButton = buttonSection
64780             .append('button')
64781             .attr('class', 'action col5 button save-button')
64782             .attr('disabled', function() {
64783                 var n = select('.commit-form textarea').node();
64784                 return (n && n.value.length) ? null : true;
64785             })
64786             .on('click.save', function() {
64787                 dispatch$$1.call('save', this, {
64788                     comment: commentField.node().value
64789                 });
64790             });
64791
64792         saveButton
64793             .append('span')
64794             .attr('class', 'label')
64795             .text(t('commit.save'));
64796
64797
64798         // Changes
64799         var changeSection = body
64800             .append('div')
64801             .attr('class', 'commit-section modal-section fillL2');
64802
64803         changeSection.append('h3')
64804             .text(t('commit.changes', { count: summary.length }));
64805
64806         var li = changeSection
64807             .append('ul')
64808             .attr('class', 'changeset-list')
64809             .selectAll('li')
64810             .data(summary);
64811
64812         li = li.enter()
64813             .append('li')
64814             .on('mouseover', mouseover)
64815             .on('mouseout', mouseout)
64816             .on('click', zoomToEntity)
64817             .merge(li);
64818
64819         li.each(function(d) {
64820             select(this)
64821                 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
64822         });
64823
64824         li.append('span')
64825             .attr('class', 'change-type')
64826             .text(function(d) { return t('commit.' + d.changeType) + ' '; });
64827
64828         li.append('strong')
64829             .attr('class', 'entity-type')
64830             .text(function(d) {
64831                 var matched = context.presets().match(d.entity, d.graph);
64832                 return (matched && matched.name()) || utilDisplayType(d.entity.id);
64833             });
64834
64835         li.append('span')
64836             .attr('class', 'entity-name')
64837             .text(function(d) {
64838                 var name = utilDisplayName(d.entity) || '',
64839                     string = '';
64840                 if (name !== '') string += ':';
64841                 return string += ' ' + name;
64842             });
64843
64844         li.style('opacity', 0)
64845             .transition()
64846             .style('opacity', 1);
64847
64848
64849         // Call checkComment off the bat, in case a changeset
64850         // comment is recovered from localStorage
64851         utilTriggerEvent(commentField, 'input');
64852
64853
64854         function mouseover(d) {
64855             if (d.entity) {
64856                 context.surface().selectAll(
64857                     utilEntityOrMemberSelector([d.entity.id], context.graph())
64858                 ).classed('hover', true);
64859             }
64860         }
64861
64862
64863         function mouseout() {
64864             context.surface().selectAll('.hover')
64865                 .classed('hover', false);
64866         }
64867
64868
64869         function warningClick(d) {
64870             if (d.entity) {
64871                 context.map().zoomTo(d.entity);
64872                 context.enter(
64873                     modeSelect(context, [d.entity.id]).suppressMenu(true)
64874                 );
64875             }
64876         }
64877
64878
64879         function zoomToEntity(change) {
64880             var entity = change.entity;
64881             if (change.changeType !== 'deleted' &&
64882                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
64883                 context.map().zoomTo(entity);
64884                 context.surface().selectAll(
64885                     utilEntityOrMemberSelector([entity.id], context.graph()))
64886                     .classed('hover', true);
64887             }
64888         }
64889
64890
64891         function checkComment() {
64892             selectAll('.save-section .save-button')
64893                 .attr('disabled', (this.value.length ? null : true));
64894
64895             var googleWarning = clippyArea
64896                .html('')
64897                .selectAll('a')
64898                .data(this.value.match(/google/i) ? [true] : []);
64899
64900             googleWarning.exit()
64901                 .remove();
64902
64903             googleWarning.enter()
64904                .append('a')
64905                .attr('target', '_blank')
64906                .attr('tabindex', -1)
64907                .call(svgIcon('#icon-alert', 'inline'))
64908                .attr('href', t('commit.google_warning_link'))
64909                .append('span')
64910                .text(t('commit.google_warning'));
64911         }
64912     }
64913
64914     return utilRebind(commit, dispatch$$1, 'on');
64915 }
64916
64917 function uiConfirm(selection) {
64918     var modalSelection = uiModal(selection);
64919
64920     modalSelection.select('.modal')
64921         .classed('modal-alert', true);
64922
64923     var section = modalSelection.select('.content');
64924
64925     section.append('div')
64926         .attr('class', 'modal-section header');
64927
64928     section.append('div')
64929         .attr('class', 'modal-section message-text');
64930
64931     var buttons = section.append('div')
64932         .attr('class', 'modal-section buttons cf');
64933
64934
64935     modalSelection.okButton = function() {
64936         buttons
64937             .append('button')
64938             .attr('class', 'action col4')
64939             .on('click.confirm', function() {
64940                 modalSelection.remove();
64941             })
64942             .text(t('confirm.okay'));
64943
64944         return modalSelection;
64945     };
64946
64947
64948     return modalSelection;
64949 }
64950
64951 function uiConflicts(context) {
64952     var dispatch$$1 = dispatch('download', 'cancel', 'save'),
64953         list;
64954
64955
64956     function conflicts(selection$$1) {
64957         var header = selection$$1
64958             .append('div')
64959             .attr('class', 'header fillL');
64960
64961         header
64962             .append('button')
64963             .attr('class', 'fr')
64964             .on('click', function() { dispatch$$1.call('cancel'); })
64965             .call(svgIcon('#icon-close'));
64966
64967         header
64968             .append('h3')
64969             .text(t('save.conflict.header'));
64970
64971         var body = selection$$1
64972             .append('div')
64973             .attr('class', 'body fillL');
64974
64975         body
64976             .append('div')
64977             .attr('class', 'conflicts-help')
64978             .text(t('save.conflict.help'))
64979             .append('a')
64980             .attr('class', 'conflicts-download')
64981             .text(t('save.conflict.download_changes'))
64982             .on('click.download', function() { dispatch$$1.call('download'); });
64983
64984         body
64985             .append('div')
64986             .attr('class', 'conflict-container fillL3')
64987             .call(showConflict, 0);
64988
64989         body
64990             .append('div')
64991             .attr('class', 'conflicts-done')
64992             .attr('opacity', 0)
64993             .style('display', 'none')
64994             .text(t('save.conflict.done'));
64995
64996         var buttons = body
64997             .append('div')
64998             .attr('class','buttons col12 joined conflicts-buttons');
64999
65000         buttons
65001             .append('button')
65002             .attr('disabled', list.length > 1)
65003             .attr('class', 'action conflicts-button col6')
65004             .text(t('save.title'))
65005             .on('click.try_again', function() { dispatch$$1.call('save'); });
65006
65007         buttons
65008             .append('button')
65009             .attr('class', 'secondary-action conflicts-button col6')
65010             .text(t('confirm.cancel'))
65011             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
65012     }
65013
65014
65015     function showConflict(selection$$1, index) {
65016         if (index < 0 || index >= list.length) return;
65017
65018         var parent = select(selection$$1.node().parentNode);
65019
65020         // enable save button if this is the last conflict being reviewed..
65021         if (index === list.length - 1) {
65022             window.setTimeout(function() {
65023                 parent.select('.conflicts-button')
65024                     .attr('disabled', null);
65025
65026                 parent.select('.conflicts-done')
65027                     .transition()
65028                     .attr('opacity', 1)
65029                     .style('display', 'block');
65030             }, 250);
65031         }
65032
65033         var item = selection$$1
65034             .selectAll('.conflict')
65035             .data([list[index]]);
65036
65037         var enter = item.enter()
65038             .append('div')
65039             .attr('class', 'conflict');
65040
65041         enter
65042             .append('h4')
65043             .attr('class', 'conflict-count')
65044             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
65045
65046         enter
65047             .append('a')
65048             .attr('class', 'conflict-description')
65049             .attr('href', '#')
65050             .text(function(d) { return d.name; })
65051             .on('click', function(d) {
65052                 zoomToEntity(d.id);
65053                 event.preventDefault();
65054             });
65055
65056         var details = enter
65057             .append('div')
65058             .attr('class', 'conflict-detail-container');
65059
65060         details
65061             .append('ul')
65062             .attr('class', 'conflict-detail-list')
65063             .selectAll('li')
65064             .data(function(d) { return d.details || []; })
65065             .enter()
65066             .append('li')
65067             .attr('class', 'conflict-detail-item')
65068             .html(function(d) { return d; });
65069
65070         details
65071             .append('div')
65072             .attr('class', 'conflict-choices')
65073             .call(addChoices);
65074
65075         details
65076             .append('div')
65077             .attr('class', 'conflict-nav-buttons joined cf')
65078             .selectAll('button')
65079             .data(['previous', 'next'])
65080             .enter()
65081             .append('button')
65082             .text(function(d) { return t('save.conflict.' + d); })
65083             .attr('class', 'conflict-nav-button action col6')
65084             .attr('disabled', function(d, i) {
65085                 return (i === 0 && index === 0) ||
65086                     (i === 1 && index === list.length - 1) || null;
65087             })
65088             .on('click', function(d, i) {
65089                 var container = parent.select('.conflict-container'),
65090                 sign = (i === 0 ? -1 : 1);
65091
65092                 container
65093                     .selectAll('.conflict')
65094                     .remove();
65095
65096                 container
65097                     .call(showConflict, index + sign);
65098
65099                 event.preventDefault();
65100             });
65101
65102         item.exit()
65103             .remove();
65104     }
65105
65106
65107     function addChoices(selection$$1) {
65108         var choices = selection$$1
65109             .append('ul')
65110             .attr('class', 'layer-list')
65111             .selectAll('li')
65112             .data(function(d) { return d.choices || []; });
65113
65114         var enter = choices.enter()
65115             .append('li')
65116             .attr('class', 'layer');
65117
65118         var label = enter
65119             .append('label');
65120
65121         label
65122             .append('input')
65123             .attr('type', 'radio')
65124             .attr('name', function(d) { return d.id; })
65125             .on('change', function(d, i) {
65126                 var ul = this.parentNode.parentNode.parentNode;
65127                 ul.__data__.chosen = i;
65128                 choose(ul, d);
65129             });
65130
65131         label
65132             .append('span')
65133             .text(function(d) { return d.text; });
65134
65135         choices
65136             .each(function(d, i) {
65137                 var ul = this.parentNode;
65138                 if (ul.__data__.chosen === i) choose(ul, d);
65139             });
65140     }
65141
65142
65143     function choose(ul, datum) {
65144         if (event) event.preventDefault();
65145
65146         select(ul)
65147             .selectAll('li')
65148             .classed('active', function(d) { return d === datum; })
65149             .selectAll('input')
65150             .property('checked', function(d) { return d === datum; });
65151
65152         var extent$$1 = geoExtent$$1(),
65153             entity;
65154
65155         entity = context.graph().hasEntity(datum.id);
65156         if (entity) extent$$1._extend(entity.extent(context.graph()));
65157
65158         datum.action();
65159
65160         entity = context.graph().hasEntity(datum.id);
65161         if (entity) extent$$1._extend(entity.extent(context.graph()));
65162
65163         zoomToEntity(datum.id, extent$$1);
65164     }
65165
65166
65167     function zoomToEntity(id, extent$$1) {
65168         context.surface().selectAll('.hover')
65169             .classed('hover', false);
65170
65171         var entity = context.graph().hasEntity(id);
65172         if (entity) {
65173             if (extent$$1) {
65174                 context.map().trimmedExtent(extent$$1);
65175             } else {
65176                 context.map().zoomTo(entity);
65177             }
65178             context.surface().selectAll(
65179                 utilEntityOrMemberSelector([entity.id], context.graph()))
65180                 .classed('hover', true);
65181         }
65182     }
65183
65184
65185     // The conflict list should be an array of objects like:
65186     // {
65187     //     id: id,
65188     //     name: entityName(local),
65189     //     details: merge.conflicts(),
65190     //     chosen: 1,
65191     //     choices: [
65192     //         choice(id, keepMine, forceLocal),
65193     //         choice(id, keepTheirs, forceRemote)
65194     //     ]
65195     // }
65196     conflicts.list = function(_) {
65197         if (!arguments.length) return list;
65198         list = _;
65199         return conflicts;
65200     };
65201
65202
65203     return utilRebind(conflicts, dispatch$$1, 'on');
65204 }
65205
65206 function uiFlash(selection) {
65207     var modalSelection = uiModal(selection);
65208
65209     modalSelection.select('.modal')
65210         .classed('modal-flash', true);
65211
65212     modalSelection.select('.content')
65213         .classed('modal-section', true)
65214         .append('div')
65215         .attr('class', 'description');
65216
65217     modalSelection.on('click.flash', function() {
65218         modalSelection.remove();
65219     });
65220
65221     setTimeout(function() {
65222         modalSelection.remove();
65223         return true;
65224     }, 1500);
65225
65226
65227     return modalSelection;
65228 }
65229
65230 function uiLasso(context) {
65231     var group, polygon;
65232
65233     lasso.coordinates = [];
65234
65235     function lasso(selection$$1) {
65236         context.container()
65237             .classed('lasso', true);
65238
65239         group = selection$$1
65240             .append('g')
65241             .attr('class', 'lasso hide');
65242
65243         polygon = group
65244             .append('path')
65245             .attr('class', 'lasso-path');
65246
65247         group
65248             .call(uiToggle(true));
65249     }
65250
65251
65252     function draw() {
65253         if (polygon) {
65254             polygon.data([lasso.coordinates])
65255                 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
65256         }
65257     }
65258
65259
65260     lasso.extent = function () {
65261         return lasso.coordinates.reduce(function(extent$$1, point) {
65262             return extent$$1.extend(geoExtent$$1(point));
65263         }, geoExtent$$1());
65264     };
65265
65266
65267     lasso.p = function(_) {
65268         if (!arguments.length) return lasso;
65269         lasso.coordinates.push(_);
65270         draw();
65271         return lasso;
65272     };
65273
65274
65275     lasso.close = function() {
65276         if (group) {
65277             group.call(uiToggle(false, function() {
65278                 select(this).remove();
65279             }));
65280         }
65281         context.container().classed('lasso', false);
65282     };
65283
65284
65285     return lasso;
65286 }
65287
65288 function uiRadialMenu(context, operations) {
65289     var menu,
65290         center = [0, 0],
65291         tooltip;
65292
65293
65294     var radialMenu = function(selection$$1) {
65295         if (!operations.length) return;
65296
65297         selection$$1.node().parentNode.focus();
65298
65299         function click(operation) {
65300             event.stopPropagation();
65301             if (operation.disabled()) return;
65302             operation();
65303             radialMenu.close();
65304         }
65305
65306         menu = selection$$1
65307             .append('g')
65308             .attr('class', 'radial-menu')
65309             .attr('transform', 'translate(' + center + ')')
65310             .attr('opacity', 0);
65311
65312         menu
65313             .transition()
65314             .attr('opacity', 1);
65315
65316         var r = 50,
65317             a = Math.PI / 4,
65318             a0 = -Math.PI / 4,
65319             a1 = a0 + (operations.length - 1) * a;
65320
65321         menu
65322             .append('path')
65323             .attr('class', 'radial-menu-background')
65324             .attr('d', 'M' + r * Math.sin(a0) + ',' +
65325                              r * Math.cos(a0) +
65326                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
65327                              (r * Math.sin(a1) + 1e-3) + ',' +
65328                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
65329             .attr('stroke-width', 50)
65330             .attr('stroke-linecap', 'round');
65331
65332         var button = menu.selectAll()
65333             .data(operations)
65334             .enter()
65335             .append('g')
65336             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
65337             .classed('disabled', function(d) { return d.disabled(); })
65338             .attr('transform', function(d, i) {
65339                 return 'translate(' + geoRoundCoords([
65340                         r * Math.sin(a0 + i * a),
65341                         r * Math.cos(a0 + i * a)]).join(',') + ')';
65342             });
65343
65344         button
65345             .append('circle')
65346             .attr('r', 15)
65347             .on('click', click)
65348             .on('mousedown', mousedown)
65349             .on('mouseover', mouseover)
65350             .on('mouseout', mouseout);
65351
65352         button
65353             .append('use')
65354             .attr('transform', 'translate(-10,-10)')
65355             .attr('width', '20')
65356             .attr('height', '20')
65357             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
65358
65359         tooltip = select(document.body)
65360             .append('div')
65361             .attr('class', 'tooltip-inner radial-menu-tooltip');
65362
65363         function mousedown() {
65364             event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
65365         }
65366
65367         function mouseover(d, i) {
65368             var rect = context.surfaceRect(),
65369                 angle = a0 + i * a,
65370                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
65371                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
65372                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
65373                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
65374
65375             tooltip
65376                 .style('top', null)
65377                 .style('left', null)
65378                 .style('bottom', null)
65379                 .style('right', null)
65380                 .style('display', 'block')
65381                 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
65382
65383             if (i === 0) {
65384                 tooltip
65385                     .style('right', right)
65386                     .style('top', top);
65387             } else if (i >= 4) {
65388                 tooltip
65389                     .style('left', left)
65390                     .style('bottom', bottom);
65391             } else {
65392                 tooltip
65393                     .style('left', left)
65394                     .style('top', top);
65395             }
65396         }
65397
65398         function mouseout() {
65399             tooltip.style('display', 'none');
65400         }
65401     };
65402
65403
65404     radialMenu.close = function() {
65405         if (menu) {
65406             menu
65407                 .style('pointer-events', 'none')
65408                 .transition()
65409                 .attr('opacity', 0)
65410                 .remove();
65411         }
65412
65413         if (tooltip) {
65414             tooltip.remove();
65415         }
65416     };
65417
65418
65419     radialMenu.center = function(_) {
65420         if (!arguments.length) return center;
65421         center = _;
65422         return radialMenu;
65423     };
65424
65425
65426     return radialMenu;
65427 }
65428
65429 function uiSelectionList(context, selectedIDs) {
65430
65431     function selectEntity(entity) {
65432         context.enter(modeSelect(context, [entity.id]).suppressMenu(true));
65433     }
65434
65435
65436     function deselectEntity(entity) {
65437         event.stopPropagation();
65438         var index = selectedIDs.indexOf(entity.id);
65439         if (index > -1) {
65440             selectedIDs.splice(index, 1);
65441         }
65442         context.enter(modeSelect(context, selectedIDs).suppressMenu(true));
65443     }
65444
65445
65446     function selectionList(selection$$1) {
65447         selection$$1.classed('selection-list-pane', true);
65448
65449         var header = selection$$1
65450             .append('div')
65451             .attr('class', 'header fillL cf');
65452
65453         header
65454             .append('h3')
65455             .text(t('inspector.multiselect'));
65456
65457         var listWrap = selection$$1
65458             .append('div')
65459             .attr('class', 'inspector-body');
65460
65461         var list = listWrap
65462             .append('div')
65463             .attr('class', 'feature-list cf');
65464
65465         context.history().on('change.selection-list', drawList);
65466         drawList();
65467
65468
65469         function drawList() {
65470             var entities = selectedIDs
65471                 .map(function(id) { return context.hasEntity(id); })
65472                 .filter(function(entity) { return entity; });
65473
65474             var items = list.selectAll('.feature-list-item')
65475                 .data(entities, osmEntity$$1.key);
65476
65477             items.exit()
65478                 .remove();
65479
65480             // Enter
65481             var enter = items.enter()
65482                 .append('div')
65483                 .attr('class', 'feature-list-item')
65484                 .on('click', selectEntity);
65485
65486             var label = enter
65487                 .append('button')
65488                 .attr('class', 'label');
65489
65490             enter
65491                 .append('button')
65492                 .attr('class', 'close')
65493                 .on('click', deselectEntity)
65494                 .call(svgIcon('#icon-close'));
65495
65496             label
65497                 .append('span')
65498                 .attr('class', 'entity-geom-icon')
65499                 .call(svgIcon('', 'pre-text'));
65500
65501             label
65502                 .append('span')
65503                 .attr('class', 'entity-type');
65504
65505             label
65506                 .append('span')
65507                 .attr('class', 'entity-name');
65508
65509             // Update
65510             items = items.merge(enter);
65511
65512             items.selectAll('.entity-geom-icon use')
65513                 .attr('href', function() {
65514                     var entity = this.parentNode.parentNode.__data__;
65515                     return '#icon-' + context.geometry(entity.id);
65516                 });
65517
65518             items.selectAll('.entity-type')
65519                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
65520
65521             items.selectAll('.entity-name')
65522                 .text(function(entity) { return utilDisplayName(entity); });
65523         }
65524     }
65525
65526     return selectionList;
65527 }
65528
65529 function uiSourceSwitch(context) {
65530     var keys$$1;
65531
65532
65533     function click() {
65534         event.preventDefault();
65535
65536         if (context.history().hasChanges() &&
65537             !window.confirm(t('source_switch.lose_changes'))) return;
65538
65539         var live = select(this)
65540             .classed('live');
65541
65542         context.connection()
65543             .switch(live ? keys$$1[1] : keys$$1[0]);
65544
65545         context.enter(modeBrowse$$1(context));
65546         context.flush();
65547
65548         select(this)
65549             .text(live ? t('source_switch.dev') : t('source_switch.live'))
65550             .classed('live', !live);
65551     }
65552
65553     var sourceSwitch = function(selection$$1) {
65554         selection$$1
65555             .append('a')
65556             .attr('href', '#')
65557             .text(t('source_switch.live'))
65558             .classed('live', true)
65559             .attr('tabindex', -1)
65560             .on('click', click);
65561     };
65562
65563
65564     sourceSwitch.keys = function(_) {
65565         if (!arguments.length) return keys$$1;
65566         keys$$1 = _;
65567         return sourceSwitch;
65568     };
65569
65570
65571     return sourceSwitch;
65572 }
65573
65574 function uiSuccess(context) {
65575     var dispatch$$1 = dispatch('cancel'),
65576         changeset;
65577
65578
65579     function success(selection$$1) {
65580         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
65581             ' ' + context.connection().changesetURL(changeset.id);
65582
65583         var header = selection$$1
65584             .append('div')
65585             .attr('class', 'header fillL');
65586
65587         header
65588             .append('button')
65589             .attr('class', 'fr')
65590             .on('click', function() { dispatch$$1.call('cancel'); })
65591             .call(svgIcon('#icon-close'));
65592
65593         header
65594             .append('h3')
65595             .text(t('success.just_edited'));
65596
65597         var body = selection$$1
65598             .append('div')
65599             .attr('class', 'body save-success fillL');
65600
65601         body
65602             .append('p')
65603             .html(t('success.help_html'));
65604
65605         body
65606             .append('a')
65607             .attr('class', 'details')
65608             .attr('target', '_blank')
65609             .attr('tabindex', -1)
65610             .call(svgIcon('#icon-out-link', 'inline'))
65611             .attr('href', t('success.help_link_url'))
65612             .append('span')
65613             .text(t('success.help_link_text'));
65614
65615         var changesetURL = context.connection().changesetURL(changeset.id);
65616
65617         body
65618             .append('a')
65619             .attr('class', 'button col12 osm')
65620             .attr('target', '_blank')
65621             .attr('href', changesetURL)
65622             .text(t('success.view_on_osm'));
65623
65624         var sharing = {
65625             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
65626             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
65627             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
65628         };
65629
65630         body.selectAll('.button.social')
65631             .data(entries(sharing))
65632             .enter()
65633             .append('a')
65634             .attr('class', 'button social col4')
65635             .attr('target', '_blank')
65636             .attr('href', function(d) { return d.value; })
65637             .call(tooltip()
65638                 .title(function(d) { return t('success.' + d.key); })
65639                 .placement('bottom'))
65640             .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
65641     }
65642
65643
65644     success.changeset = function(_) {
65645         if (!arguments.length) return changeset;
65646         changeset = _;
65647         return success;
65648     };
65649
65650
65651     return utilRebind(success, dispatch$$1, 'on');
65652 }
65653
65654 function coreHistory(context) {
65655     var stack$$1, index, tree$$1,
65656         imageryUsed = ['Bing'],
65657         dispatch$$1 = dispatch('change', 'undone', 'redone'),
65658         lock = utilSessionMutex('lock');
65659
65660
65661     function perform(actions) {
65662         actions = Array.prototype.slice.call(actions);
65663
65664         var annotation;
65665
65666         if (!lodash.isFunction(lodash.last(actions))) {
65667             annotation = actions.pop();
65668         }
65669
65670         stack$$1[index].transform = context.projection.transform();
65671         stack$$1[index].selectedIDs = context.selectedIDs();
65672
65673         var graph = stack$$1[index].graph;
65674         for (var i = 0; i < actions.length; i++) {
65675             graph = actions[i](graph);
65676         }
65677
65678         return {
65679             graph: graph,
65680             annotation: annotation,
65681             imageryUsed: imageryUsed
65682         };
65683     }
65684
65685
65686     function change(previous) {
65687         var difference = coreDifference(previous, history.graph());
65688         dispatch$$1.call('change', this, difference);
65689         return difference;
65690     }
65691
65692
65693     // iD uses namespaced keys so multiple installations do not conflict
65694     function getKey(n) {
65695         return 'iD_' + window.location.origin + '_' + n;
65696     }
65697
65698
65699     var history = {
65700
65701         graph: function() {
65702             return stack$$1[index].graph;
65703         },
65704
65705
65706         base: function() {
65707             return stack$$1[0].graph;
65708         },
65709
65710
65711         merge: function(entities, extent$$1) {
65712             stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
65713             tree$$1.rebase(entities, false);
65714
65715             dispatch$$1.call('change', this, undefined, extent$$1);
65716         },
65717
65718
65719         perform: function() {
65720             var previous = stack$$1[index].graph;
65721
65722             stack$$1 = stack$$1.slice(0, index + 1);
65723             stack$$1.push(perform(arguments));
65724             index++;
65725
65726             return change(previous);
65727         },
65728
65729
65730         replace: function() {
65731             var previous = stack$$1[index].graph;
65732
65733             // assert(index == stack.length - 1)
65734             stack$$1[index] = perform(arguments);
65735
65736             return change(previous);
65737         },
65738
65739
65740         pop: function() {
65741             var previous = stack$$1[index].graph;
65742
65743             if (index > 0) {
65744                 index--;
65745                 stack$$1.pop();
65746                 return change(previous);
65747             }
65748         },
65749
65750
65751         // Same as calling pop and then perform
65752         overwrite: function() {
65753             var previous = stack$$1[index].graph;
65754
65755             if (index > 0) {
65756                 index--;
65757                 stack$$1.pop();
65758             }
65759             stack$$1 = stack$$1.slice(0, index + 1);
65760             stack$$1.push(perform(arguments));
65761             index++;
65762
65763             return change(previous);
65764         },
65765
65766
65767         undo: function() {
65768             var previous = stack$$1[index].graph;
65769
65770             // Pop to the next annotated state.
65771             while (index > 0) {
65772                 index--;
65773                 if (stack$$1[index].annotation) break;
65774             }
65775
65776             dispatch$$1.call('undone', this, stack$$1[index]);
65777             return change(previous);
65778         },
65779
65780
65781         redo: function() {
65782             var previous = stack$$1[index].graph;
65783
65784             while (index < stack$$1.length - 1) {
65785                 index++;
65786                 if (stack$$1[index].annotation) break;
65787             }
65788
65789             dispatch$$1.call('redone', this, stack$$1[index]);
65790             return change(previous);
65791         },
65792
65793
65794         undoAnnotation: function() {
65795             var i = index;
65796             while (i >= 0) {
65797                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
65798                 i--;
65799             }
65800         },
65801
65802
65803         redoAnnotation: function() {
65804             var i = index + 1;
65805             while (i <= stack$$1.length - 1) {
65806                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
65807                 i++;
65808             }
65809         },
65810
65811
65812         intersects: function(extent$$1) {
65813             return tree$$1.intersects(extent$$1, stack$$1[index].graph);
65814         },
65815
65816
65817         difference: function() {
65818             var base = stack$$1[0].graph,
65819                 head = stack$$1[index].graph;
65820             return coreDifference(base, head);
65821         },
65822
65823
65824         changes: function(action) {
65825             var base = stack$$1[0].graph,
65826                 head = stack$$1[index].graph;
65827
65828             if (action) {
65829                 head = action(head);
65830             }
65831
65832             var difference = coreDifference(base, head);
65833
65834             return {
65835                 modified: difference.modified(),
65836                 created: difference.created(),
65837                 deleted: difference.deleted()
65838             };
65839         },
65840
65841
65842         validate: function(changes) {
65843             return lodash(Validations)
65844                 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
65845                 .flatten()
65846                 .value();
65847         },
65848
65849
65850         hasChanges: function() {
65851             return this.difference().length() > 0;
65852         },
65853
65854
65855         imageryUsed: function(sources) {
65856             if (sources) {
65857                 imageryUsed = sources;
65858                 return history;
65859             } else {
65860                 return lodash(stack$$1.slice(1, index + 1))
65861                     .map('imageryUsed')
65862                     .flatten()
65863                     .uniq()
65864                     .without(undefined, 'Custom')
65865                     .value();
65866             }
65867         },
65868
65869
65870         reset: function() {
65871             stack$$1 = [{graph: coreGraph$$1()}];
65872             index = 0;
65873             tree$$1 = coreTree(stack$$1[0].graph);
65874             dispatch$$1.call('change');
65875             return history;
65876         },
65877
65878
65879         toJSON: function() {
65880             if (!this.hasChanges()) return;
65881
65882             var allEntities = {},
65883                 baseEntities = {},
65884                 base = stack$$1[0];
65885
65886             var s = stack$$1.map(function(i) {
65887                 var modified = [], deleted = [];
65888
65889                 lodash.forEach(i.graph.entities, function(entity, id) {
65890                     if (entity) {
65891                         var key = osmEntity$$1.key(entity);
65892                         allEntities[key] = entity;
65893                         modified.push(key);
65894                     } else {
65895                         deleted.push(id);
65896                     }
65897
65898                     // make sure that the originals of changed or deleted entities get merged
65899                     // into the base of the stack after restoring the data from JSON.
65900                     if (id in base.graph.entities) {
65901                         baseEntities[id] = base.graph.entities[id];
65902                     }
65903                     // get originals of parent entities too
65904                     lodash.forEach(base.graph._parentWays[id], function(parentId) {
65905                         if (parentId in base.graph.entities) {
65906                             baseEntities[parentId] = base.graph.entities[parentId];
65907                         }
65908                     });
65909                 });
65910
65911                 var x = {};
65912
65913                 if (modified.length) x.modified = modified;
65914                 if (deleted.length) x.deleted = deleted;
65915                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
65916                 if (i.annotation) x.annotation = i.annotation;
65917
65918                 return x;
65919             });
65920
65921             return JSON.stringify({
65922                 version: 3,
65923                 entities: lodash.values(allEntities),
65924                 baseEntities: lodash.values(baseEntities),
65925                 stack: s,
65926                 nextIDs: osmEntity$$1.id.next,
65927                 index: index
65928             });
65929         },
65930
65931
65932         fromJSON: function(json$$1, loadChildNodes) {
65933             var h = JSON.parse(json$$1),
65934                 loadComplete = true;
65935
65936             osmEntity$$1.id.next = h.nextIDs;
65937             index = h.index;
65938
65939             if (h.version === 2 || h.version === 3) {
65940                 var allEntities = {};
65941
65942                 h.entities.forEach(function(entity) {
65943                     allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
65944                 });
65945
65946                 if (h.version === 3) {
65947                     // This merges originals for changed entities into the base of
65948                     // the stack even if the current stack doesn't have them (for
65949                     // example when iD has been restarted in a different region)
65950                     var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
65951                     stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
65952                     tree$$1.rebase(baseEntities, true);
65953
65954                     // When we restore a modified way, we also need to fetch any missing
65955                     // childnodes that would normally have been downloaded with it.. #2142
65956                     if (loadChildNodes) {
65957                         var missing =  lodash(baseEntities)
65958                                 .filter({ type: 'way' })
65959                                 .map('nodes')
65960                                 .flatten()
65961                                 .uniq()
65962                                 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
65963                                 .value();
65964
65965                         if (!lodash.isEmpty(missing)) {
65966                             loadComplete = false;
65967                             context.redrawEnable(false);
65968
65969                             var loading = uiLoading(context).blocking(true);
65970                             context.container().call(loading);
65971
65972                             var childNodesLoaded = function(err, result) {
65973                                 if (!err) {
65974                                     var visible = lodash.groupBy(result.data, 'visible');
65975                                     if (!lodash.isEmpty(visible.true)) {
65976                                         missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
65977                                         stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
65978                                         tree$$1.rebase(visible.true, true);
65979                                     }
65980
65981                                     // fetch older versions of nodes that were deleted..
65982                                     lodash.each(visible.false, function(entity) {
65983                                         context.connection()
65984                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
65985                                     });
65986                                 }
65987
65988                                 if (err || lodash.isEmpty(missing)) {
65989                                     loading.close();
65990                                     context.redrawEnable(true);
65991                                     dispatch$$1.call('change');
65992                                 }
65993                             };
65994
65995                             context.connection().loadMultiple(missing, childNodesLoaded);
65996                         }
65997                     }
65998                 }
65999
66000                 stack$$1 = h.stack.map(function(d) {
66001                     var entities = {}, entity;
66002
66003                     if (d.modified) {
66004                         d.modified.forEach(function(key) {
66005                             entity = allEntities[key];
66006                             entities[entity.id] = entity;
66007                         });
66008                     }
66009
66010                     if (d.deleted) {
66011                         d.deleted.forEach(function(id) {
66012                             entities[id] = undefined;
66013                         });
66014                     }
66015
66016                     return {
66017                         graph: coreGraph$$1(stack$$1[0].graph).load(entities),
66018                         annotation: d.annotation,
66019                         imageryUsed: d.imageryUsed
66020                     };
66021                 });
66022
66023             } else { // original version
66024                 stack$$1 = h.stack.map(function(d) {
66025                     var entities = {};
66026
66027                     for (var i in d.entities) {
66028                         var entity = d.entities[i];
66029                         entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
66030                     }
66031
66032                     d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
66033                     return d;
66034                 });
66035             }
66036
66037             if (loadComplete) {
66038                 dispatch$$1.call('change');
66039             }
66040
66041             return history;
66042         },
66043
66044
66045         save: function() {
66046             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
66047             return history;
66048         },
66049
66050
66051         clearSaved: function() {
66052             context.debouncedSave.cancel();
66053             if (lock.locked()) context.storage(getKey('saved_history'), null);
66054             return history;
66055         },
66056
66057
66058         lock: function() {
66059             return lock.lock();
66060         },
66061
66062
66063         unlock: function() {
66064             lock.unlock();
66065         },
66066
66067
66068         // is iD not open in another window and it detects that
66069         // there's a history stored in localStorage that's recoverable?
66070         restorableChanges: function() {
66071             return lock.locked() && !!context.storage(getKey('saved_history'));
66072         },
66073
66074
66075         // load history from a version stored in localStorage
66076         restore: function() {
66077             if (!lock.locked()) return;
66078
66079             var json$$1 = context.storage(getKey('saved_history'));
66080             if (json$$1) history.fromJSON(json$$1, true);
66081         },
66082
66083
66084         _getKey: getKey
66085
66086     };
66087
66088
66089     history.reset();
66090
66091     return utilRebind(history, dispatch$$1, 'on');
66092 }
66093
66094 function presetCollection(collection) {
66095     var maxSearchResults = 50,
66096         maxSuggestionResults = 10;
66097
66098     var presets = {
66099
66100         collection: collection,
66101
66102
66103         item: function(id) {
66104             return lodash.find(collection, function(d) {
66105                 return d.id === id;
66106             });
66107         },
66108
66109
66110         matchGeometry: function(geometry) {
66111             return presetCollection(collection.filter(function(d) {
66112                 return d.matchGeometry(geometry);
66113             }));
66114         },
66115
66116
66117         search: function(value, geometry) {
66118             if (!value) return this;
66119
66120             function leading(a) {
66121                 var index = a.indexOf(value);
66122                 return index === 0 || a[index - 1] === ' ';
66123             }
66124
66125             function suggestionName(name) {
66126                 var nameArray = name.split(' - ');
66127                 if (nameArray.length > 1) {
66128                     name = nameArray.slice(0, nameArray.length - 1).join(' - ');
66129                 }
66130                 return name.toLowerCase();
66131             }
66132
66133
66134             value = value.toLowerCase();
66135
66136             var searchable = lodash.filter(collection, function(a) {
66137                     return a.searchable !== false && a.suggestion !== true;
66138                 }),
66139                 suggestions = lodash.filter(collection, function(a) {
66140                     return a.suggestion === true;
66141                 });
66142
66143
66144             // matches value to preset.name
66145             var leading_name = lodash.filter(searchable, function(a) {
66146                     return leading(a.name().toLowerCase());
66147                 }).sort(function(a, b) {
66148                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
66149                     if (i === 0) return a.name().length - b.name().length;
66150                     else return i;
66151                 });
66152
66153             // matches value to preset.terms values
66154             var leading_terms = lodash.filter(searchable, function(a) {
66155                     return lodash.some(a.terms() || [], leading);
66156                 });
66157
66158             // matches value to preset.tags values
66159             var leading_tag_values = lodash.filter(searchable, function(a) {
66160                     return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
66161                 });
66162
66163
66164             // finds close matches to value in preset.name
66165             var similar_name = searchable.map(function(a) {
66166                     return {
66167                         preset: a,
66168                         dist: utilEditDistance(value, a.name())
66169                     };
66170                 }).filter(function(a) {
66171                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
66172                 }).sort(function(a, b) {
66173                     return a.dist - b.dist;
66174                 }).map(function(a) {
66175                     return a.preset;
66176                 });
66177
66178             // finds close matches to value in preset.terms
66179             var similar_terms = lodash.filter(searchable, function(a) {
66180                     return lodash.some(a.terms() || [], function(b) {
66181                         return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
66182                     });
66183                 });
66184
66185             var leading_suggestions = lodash.filter(suggestions, function(a) {
66186                     return leading(suggestionName(a.name()));
66187                 }).sort(function(a, b) {
66188                     a = suggestionName(a.name());
66189                     b = suggestionName(b.name());
66190                     var i = a.indexOf(value) - b.indexOf(value);
66191                     if (i === 0) return a.length - b.length;
66192                     else return i;
66193                 });
66194
66195             var similar_suggestions = suggestions.map(function(a) {
66196                     return {
66197                         preset: a,
66198                         dist: utilEditDistance(value, suggestionName(a.name()))
66199                     };
66200                 }).filter(function(a) {
66201                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
66202                 }).sort(function(a, b) {
66203                     return a.dist - b.dist;
66204                 }).map(function(a) {
66205                     return a.preset;
66206                 });
66207
66208             var other = presets.item(geometry);
66209
66210             var results = leading_name.concat(
66211                     leading_terms,
66212                     leading_tag_values,
66213                     leading_suggestions.slice(0, maxSuggestionResults + 5),
66214                     similar_name,
66215                     similar_terms,
66216                     similar_suggestions.slice(0, maxSuggestionResults)
66217                 ).slice(0, maxSearchResults - 1);
66218
66219             return presetCollection(lodash.uniq(results.concat(other)));
66220         }
66221     };
66222
66223
66224     return presets;
66225 }
66226
66227 function presetCategory(id, category, all) {
66228     category = lodash.clone(category);
66229
66230     category.id = id;
66231
66232
66233     category.members = presetCollection(category.members.map(function(id) {
66234         return all.item(id);
66235     }));
66236
66237
66238     category.matchGeometry = function(geometry) {
66239         return category.geometry.indexOf(geometry) >= 0;
66240     };
66241
66242
66243     category.matchScore = function() {
66244         return -1;
66245     };
66246
66247
66248     category.name = function() {
66249         return t('presets.categories.' + id + '.name', {'default': id});
66250     };
66251
66252
66253     category.terms = function() {
66254         return [];
66255     };
66256
66257
66258     return category;
66259 }
66260
66261 function presetField(id, field) {
66262     field = lodash.clone(field);
66263
66264     field.id = id;
66265
66266
66267     field.matchGeometry = function(geometry) {
66268         return !field.geometry || field.geometry === geometry;
66269     };
66270
66271
66272     field.t = function(scope, options) {
66273         return t('presets.fields.' + id + '.' + scope, options);
66274     };
66275
66276
66277     field.label = function() {
66278         return field.t('label', {'default': id});
66279     };
66280
66281
66282     var placeholder = field.placeholder;
66283     field.placeholder = function() {
66284         return field.t('placeholder', {'default': placeholder});
66285     };
66286
66287
66288     return field;
66289 }
66290
66291 function presetPreset(id, preset, fields) {
66292     preset = lodash.clone(preset);
66293
66294     preset.id = id;
66295     preset.fields = (preset.fields || []).map(getFields);
66296     preset.geometry = (preset.geometry || []);
66297
66298
66299     function getFields(f) {
66300         return fields[f];
66301     }
66302
66303
66304     preset.matchGeometry = function(geometry) {
66305         return preset.geometry.indexOf(geometry) >= 0;
66306     };
66307
66308
66309     var matchScore = preset.matchScore || 1;
66310     preset.matchScore = function(entity) {
66311         var tags = preset.tags,
66312             score = 0;
66313
66314         for (var t$$1 in tags) {
66315             if (entity.tags[t$$1] === tags[t$$1]) {
66316                 score += matchScore;
66317             } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
66318                 score += matchScore / 2;
66319             } else {
66320                 return -1;
66321             }
66322         }
66323
66324         return score;
66325     };
66326
66327
66328     preset.t = function(scope, options) {
66329         return t('presets.presets.' + id + '.' + scope, options);
66330     };
66331
66332
66333     var name = preset.name || '';
66334     preset.name = function() {
66335         if (preset.suggestion) {
66336             id = id.split('/');
66337             id = id[0] + '/' + id[1];
66338             return name + ' - ' + t('presets.presets.' + id + '.name');
66339         }
66340         return preset.t('name', {'default': name});
66341     };
66342
66343
66344     preset.terms = function() {
66345         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
66346     };
66347
66348
66349     preset.isFallback = function() {
66350         var tagCount = Object.keys(preset.tags).length;
66351         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
66352     };
66353
66354
66355     preset.reference = function(geometry) {
66356         var key = Object.keys(preset.tags)[0],
66357             value = preset.tags[key];
66358
66359         if (geometry === 'relation' && key === 'type') {
66360             if (value in preset.tags) {
66361                 key = value;
66362                 value = preset.tags[key];
66363             } else {
66364                 return { rtype: value };
66365             }
66366         }
66367
66368         if (value === '*') {
66369             return { key: key };
66370         } else {
66371             return { key: key, value: value };
66372         }
66373     };
66374
66375
66376     var removeTags = preset.removeTags || preset.tags;
66377     preset.removeTags = function(tags, geometry) {
66378         tags = lodash.omit(tags, lodash.keys(removeTags));
66379
66380         for (var f in preset.fields) {
66381             var field = preset.fields[f];
66382             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
66383                 delete tags[field.key];
66384             }
66385         }
66386
66387         delete tags.area;
66388         return tags;
66389     };
66390
66391
66392     var applyTags = preset.addTags || preset.tags;
66393     preset.applyTags = function(tags, geometry) {
66394         var k;
66395
66396         tags = lodash.clone(tags);
66397
66398         for (k in applyTags) {
66399             if (applyTags[k] === '*') {
66400                 tags[k] = 'yes';
66401             } else {
66402                 tags[k] = applyTags[k];
66403             }
66404         }
66405
66406         // Add area=yes if necessary.
66407         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
66408         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
66409         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
66410         if (geometry === 'area') {
66411             var needsAreaTag = true;
66412             if (preset.geometry.indexOf('line') === -1) {
66413                 for (k in applyTags) {
66414                     if (k in areaKeys) {
66415                         needsAreaTag = false;
66416                         break;
66417                     }
66418                 }
66419             }
66420             if (needsAreaTag) {
66421                 tags.area = 'yes';
66422             }
66423         }
66424
66425         for (var f in preset.fields) {
66426             var field = preset.fields[f];
66427             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
66428                 tags[field.key] = field.default;
66429             }
66430         }
66431
66432         return tags;
66433     };
66434
66435
66436     return preset;
66437 }
66438
66439 function presetIndex() {
66440     // a presetCollection with methods for
66441     // loading new data and returning defaults
66442
66443     var all = presetCollection([]),
66444         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
66445         fields = {},
66446         universal = [],
66447         recent = presetCollection([]);
66448
66449     // Index of presets by (geometry, tag key).
66450     var index = {
66451         point: {},
66452         vertex: {},
66453         line: {},
66454         area: {},
66455         relation: {}
66456     };
66457
66458     all.match = function(entity, resolver) {
66459         var geometry = entity.geometry(resolver);
66460
66461         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
66462         if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
66463             geometry = 'point';
66464         }
66465
66466         var geometryMatches = index[geometry],
66467             best = -1,
66468             match;
66469
66470         for (var k in entity.tags) {
66471             var keyMatches = geometryMatches[k];
66472             if (!keyMatches) continue;
66473
66474             for (var i = 0; i < keyMatches.length; i++) {
66475                 var score = keyMatches[i].matchScore(entity);
66476                 if (score > best) {
66477                     best = score;
66478                     match = keyMatches[i];
66479                 }
66480             }
66481         }
66482
66483         return match || all.item(geometry);
66484     };
66485
66486
66487     // Because of the open nature of tagging, iD will never have a complete
66488     // list of tags used in OSM, so we want it to have logic like "assume
66489     // that a closed way with an amenity tag is an area, unless the amenity
66490     // is one of these specific types". This function computes a structure
66491     // that allows testing of such conditions, based on the presets designated
66492     // as as supporting (or not supporting) the area geometry.
66493     //
66494     // The returned object L is a whitelist/blacklist of tags. A closed way
66495     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
66496     // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
66497     // and the subkeys form the blacklist.
66498     all.areaKeys = function() {
66499         var areaKeys = {},
66500             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
66501             presets = lodash.reject(all.collection, 'suggestion');
66502
66503         // whitelist
66504         presets.forEach(function(d) {
66505             for (var key in d.tags) break;
66506             if (!key) return;
66507             if (ignore.indexOf(key) !== -1) return;
66508
66509             if (d.geometry.indexOf('area') !== -1) {
66510                 areaKeys[key] = areaKeys[key] || {};
66511             }
66512         });
66513
66514         // blacklist
66515         presets.forEach(function(d) {
66516             for (var key in d.tags) break;
66517             if (!key) return;
66518             if (ignore.indexOf(key) !== -1) return;
66519
66520             var value = d.tags[key];
66521             if (d.geometry.indexOf('area') === -1 &&
66522                 d.geometry.indexOf('line') !== -1 &&
66523                 key in areaKeys && value !== '*') {
66524                 areaKeys[key][value] = true;
66525             }
66526         });
66527
66528         return areaKeys;
66529     };
66530
66531
66532     all.init = function() {
66533         var d = data.presets;
66534
66535         if (d.fields) {
66536             lodash.forEach(d.fields, function(d, id) {
66537                 fields[id] = presetField(id, d);
66538                 if (d.universal) universal.push(fields[id]);
66539             });
66540         }
66541
66542         if (d.presets) {
66543             lodash.forEach(d.presets, function(d, id) {
66544                 all.collection.push(presetPreset(id, d, fields));
66545             });
66546         }
66547
66548         if (d.categories) {
66549             lodash.forEach(d.categories, function(d, id) {
66550                 all.collection.push(presetCategory(id, d, all));
66551             });
66552         }
66553
66554         if (d.defaults) {
66555             var getItem = lodash.bind(all.item, all);
66556             defaults = {
66557                 area: presetCollection(d.defaults.area.map(getItem)),
66558                 line: presetCollection(d.defaults.line.map(getItem)),
66559                 point: presetCollection(d.defaults.point.map(getItem)),
66560                 vertex: presetCollection(d.defaults.vertex.map(getItem)),
66561                 relation: presetCollection(d.defaults.relation.map(getItem))
66562             };
66563         }
66564
66565         for (var i = 0; i < all.collection.length; i++) {
66566             var preset = all.collection[i],
66567                 geometry = preset.geometry;
66568
66569             for (var j = 0; j < geometry.length; j++) {
66570                 var g = index[geometry[j]];
66571                 for (var k in preset.tags) {
66572                     (g[k] = g[k] || []).push(preset);
66573                 }
66574             }
66575         }
66576
66577         return all;
66578     };
66579
66580     all.field = function(id) {
66581         return fields[id];
66582     };
66583
66584     all.universal = function() {
66585         return universal;
66586     };
66587
66588     all.defaults = function(geometry, n) {
66589         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
66590             def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
66591         return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
66592     };
66593
66594     all.choose = function(preset) {
66595         if (!preset.isFallback()) {
66596             recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
66597         }
66598         return all;
66599     };
66600
66601     return all;
66602 }
66603
66604 var areaKeys = {};
66605
66606 function setAreaKeys(value) {
66607     areaKeys = value;
66608 }
66609
66610
66611 function coreContext() {
66612     addTranslation('en', en);
66613     setLocale('en');
66614
66615     var dispatch$$1 = dispatch('enter', 'exit', 'change'),
66616         context = {};
66617
66618     // https://github.com/openstreetmap/iD/issues/772
66619     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
66620     var storage;
66621     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
66622     storage = storage || (function() {
66623         var s = {};
66624         return {
66625             getItem: function(k) { return s[k]; },
66626             setItem: function(k, v) { s[k] = v; },
66627             removeItem: function(k) { delete s[k]; }
66628         };
66629     })();
66630
66631     context.storage = function(k, v) {
66632         try {
66633             if (arguments.length === 1) return storage.getItem(k);
66634             else if (v === null) storage.removeItem(k);
66635             else storage.setItem(k, v);
66636         } catch (e) {
66637             // localstorage quota exceeded
66638             /* eslint-disable no-console */
66639             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
66640             /* eslint-enable no-console */
66641         }
66642     };
66643
66644
66645     /* Straight accessors. Avoid using these if you can. */
66646     var ui, connection, history;
66647     context.ui = function() { return ui; };
66648     context.connection = function() { return connection; };
66649     context.history = function() { return history; };
66650
66651
66652     /* Connection */
66653     function entitiesLoaded(err, result) {
66654         if (!err) history.merge(result.data, result.extent);
66655     }
66656
66657     context.preauth = function(options) {
66658         connection.switch(options);
66659         return context;
66660     };
66661
66662     context.loadTiles = function(projection, dimensions, callback) {
66663         function done(err, result) {
66664             entitiesLoaded(err, result);
66665             if (callback) callback(err, result);
66666         }
66667         connection.loadTiles(projection, dimensions, done);
66668     };
66669
66670     context.loadEntity = function(id, callback) {
66671         function done(err, result) {
66672             entitiesLoaded(err, result);
66673             if (callback) callback(err, result);
66674         }
66675         connection.loadEntity(id, done);
66676     };
66677
66678     context.zoomToEntity = function(id, zoomTo) {
66679         if (zoomTo !== false) {
66680             this.loadEntity(id, function(err, result) {
66681                 if (err) return;
66682                 var entity = lodash.find(result.data, function(e) { return e.id === id; });
66683                 if (entity) { map$$1.zoomTo(entity); }
66684             });
66685         }
66686
66687         map$$1.on('drawn.zoomToEntity', function() {
66688             if (!context.hasEntity(id)) return;
66689             map$$1.on('drawn.zoomToEntity', null);
66690             context.on('enter.zoomToEntity', null);
66691             context.enter(modeSelect(context, [id]));
66692         });
66693
66694         context.on('enter.zoomToEntity', function() {
66695             if (mode.id !== 'browse') {
66696                 map$$1.on('drawn.zoomToEntity', null);
66697                 context.on('enter.zoomToEntity', null);
66698             }
66699         });
66700     };
66701
66702     var minEditableZoom = 16;
66703     context.minEditableZoom = function(_) {
66704         if (!arguments.length) return minEditableZoom;
66705         minEditableZoom = _;
66706         connection.tileZoom(_);
66707         return context;
66708     };
66709
66710
66711     /* History */
66712     var inIntro = false;
66713     context.inIntro = function(_) {
66714         if (!arguments.length) return inIntro;
66715         inIntro = _;
66716         return context;
66717     };
66718
66719     context.save = function() {
66720         if (inIntro || (mode && mode.id === 'save') || select('.modal').size()) return;
66721         history.save();
66722         if (history.hasChanges()) return t('save.unsaved_changes');
66723     };
66724
66725
66726     /* Graph */
66727     context.hasEntity = function(id) {
66728         return history.graph().hasEntity(id);
66729     };
66730     context.entity = function(id) {
66731         return history.graph().entity(id);
66732     };
66733     context.childNodes = function(way) {
66734         return history.graph().childNodes(way);
66735     };
66736     context.geometry = function(id) {
66737         return context.entity(id).geometry(history.graph());
66738     };
66739
66740
66741     /* Modes */
66742     var mode;
66743     context.mode = function() {
66744         return mode;
66745     };
66746     context.enter = function(newMode) {
66747         if (mode) {
66748             mode.exit();
66749             dispatch$$1.call('exit', this, mode);
66750         }
66751
66752         mode = newMode;
66753         mode.enter();
66754         dispatch$$1.call('enter', this, mode);
66755     };
66756
66757     context.selectedIDs = function() {
66758         if (mode && mode.selectedIDs) {
66759             return mode.selectedIDs();
66760         } else {
66761             return [];
66762         }
66763     };
66764
66765
66766     /* Behaviors */
66767     context.install = function(behavior) {
66768         context.surface().call(behavior);
66769     };
66770     context.uninstall = function(behavior) {
66771         context.surface().call(behavior.off);
66772     };
66773
66774
66775     /* Copy/Paste */
66776     var copyIDs = [], copyGraph;
66777     context.copyGraph = function() { return copyGraph; };
66778     context.copyIDs = function(_) {
66779         if (!arguments.length) return copyIDs;
66780         copyIDs = _;
66781         copyGraph = history.graph();
66782         return context;
66783     };
66784
66785
66786     /* Background */
66787     var background;
66788     context.background = function() { return background; };
66789
66790
66791     /* Features */
66792     var features;
66793     context.features = function() { return features; };
66794     context.hasHiddenConnections = function(id) {
66795         var graph = history.graph(),
66796             entity = graph.entity(id);
66797         return features.hasHiddenConnections(entity, graph);
66798     };
66799
66800
66801     /* Presets */
66802     var presets;
66803     context.presets = function() { return presets; };
66804
66805
66806     /* Map */
66807     var map$$1;
66808     context.map = function() { return map$$1; };
66809     context.layers = function() { return map$$1.layers; };
66810     context.surface = function() { return map$$1.surface; };
66811     context.editable = function() { return map$$1.editable(); };
66812
66813     context.surfaceRect = function() {
66814         // Work around a bug in Firefox.
66815         //   http://stackoverflow.com/questions/18153989/
66816         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
66817         return context.surface().node().parentNode.getBoundingClientRect();
66818     };
66819
66820
66821     /* Debug */
66822     var debugFlags = {
66823         tile: false,
66824         collision: false,
66825         imagery: false,
66826         imperial: false,
66827         driveLeft: false
66828     };
66829     context.debugFlags = function() {
66830         return debugFlags;
66831     };
66832     context.setDebug = function(flag, val) {
66833         if (arguments.length === 1) val = true;
66834         debugFlags[flag] = val;
66835         dispatch$$1.call('change');
66836         return context;
66837     };
66838     context.getDebug = function(flag) {
66839         return flag && debugFlags[flag];
66840     };
66841
66842
66843     /* Container */
66844     var container, embed;
66845     context.container = function(_) {
66846         if (!arguments.length) return container;
66847         container = _;
66848         container.classed('id-container', true);
66849         return context;
66850     };
66851     context.embed = function(_) {
66852         if (!arguments.length) return embed;
66853         embed = _;
66854         return context;
66855     };
66856
66857
66858     /* Assets */
66859     var assetPath = '';
66860     context.assetPath = function(_) {
66861         if (!arguments.length) return assetPath;
66862         assetPath = _;
66863         return context;
66864     };
66865
66866     var assetMap = {};
66867     context.assetMap = function(_) {
66868         if (!arguments.length) return assetMap;
66869         assetMap = _;
66870         return context;
66871     };
66872
66873     context.asset = function(_) {
66874         var filename = assetPath + _;
66875         return assetMap[filename] || filename;
66876     };
66877
66878     context.imagePath = function(_) {
66879         return context.asset('img/' + _);
66880     };
66881
66882
66883     /* locales */
66884     // `locale` variable contains a "requested locale".
66885     // It won't become the `currentLocale` until after loadLocale() is called.
66886     var locale, localePath;
66887
66888     context.locale = function(loc, path$$1) {
66889         if (!arguments.length) return currentLocale;
66890         locale = loc;
66891         localePath = path$$1;
66892         return context;
66893     };
66894
66895     context.loadLocale = function(callback) {
66896         if (locale && locale !== 'en' && dataLocales.hasOwnProperty(locale)) {
66897             localePath = localePath || context.asset('locales/' + locale + '.json');
66898             json(localePath, function(err, result) {
66899                 if (!err) {
66900                     addTranslation(locale, result[locale]);
66901                     setLocale(locale);
66902                     utilDetect(true);
66903                 }
66904                 if (callback) {
66905                     callback(err);
66906                 }
66907             });
66908         } else {
66909             if (locale) {
66910                 setLocale(locale);
66911                 utilDetect(true);
66912             }
66913             if (callback) {
66914                 callback();
66915             }
66916         }
66917     };
66918
66919
66920     /* reset (aka flush) */
66921     context.reset = context.flush = function() {
66922         context.debouncedSave.cancel();
66923         lodash.each(services, function(service) {
66924             if (service && typeof service.reset === 'function') {
66925                 service.reset(context);
66926             }
66927         });
66928         features.reset();
66929         history.reset();
66930         return context;
66931     };
66932
66933
66934     /* Init */
66935     context.version = '2.0.2';
66936
66937     context.projection = geoRawMercator();
66938
66939     locale = utilDetect().locale;
66940     if (locale && !dataLocales.hasOwnProperty(locale)) {
66941         locale = locale.split('-')[0];
66942     }
66943
66944     history = coreHistory(context);
66945     context.graph = history.graph;
66946     context.changes = history.changes;
66947     context.intersects = history.intersects;
66948
66949     // Debounce save, since it's a synchronous localStorage write,
66950     // and history changes can happen frequently (e.g. when dragging).
66951     context.debouncedSave = lodash.debounce(context.save, 350);
66952     function withDebouncedSave(fn) {
66953         return function() {
66954             var result = fn.apply(history, arguments);
66955             context.debouncedSave();
66956             return result;
66957         };
66958     }
66959
66960     context.perform = withDebouncedSave(history.perform);
66961     context.replace = withDebouncedSave(history.replace);
66962     context.pop = withDebouncedSave(history.pop);
66963     context.overwrite = withDebouncedSave(history.overwrite);
66964     context.undo = withDebouncedSave(history.undo);
66965     context.redo = withDebouncedSave(history.redo);
66966
66967     ui = uiInit(context);
66968
66969     connection = services.osm;
66970     background = rendererBackground(context);
66971     features = rendererFeatures(context);
66972     presets = presetIndex();
66973
66974     map$$1 = rendererMap(context);
66975     context.mouse = map$$1.mouse;
66976     context.extent = map$$1.extent;
66977     context.pan = map$$1.pan;
66978     context.zoomIn = map$$1.zoomIn;
66979     context.zoomOut = map$$1.zoomOut;
66980     context.zoomInFurther = map$$1.zoomInFurther;
66981     context.zoomOutFurther = map$$1.zoomOutFurther;
66982     context.redrawEnable = map$$1.redrawEnable;
66983
66984     lodash.each(services, function(service) {
66985         if (service && typeof service.init === 'function') {
66986             service.init(context);
66987         }
66988     });
66989
66990     background.init();
66991     presets.init();
66992     areaKeys = presets.areaKeys();
66993
66994
66995     return utilRebind(context, dispatch$$1, 'on');
66996 }
66997
66998 function osmWay() {
66999     if (!(this instanceof osmWay)) {
67000         return (new osmWay()).initialize(arguments);
67001     } else if (arguments.length) {
67002         this.initialize(arguments);
67003     }
67004 }
67005
67006
67007 osmEntity$$1.way = osmWay;
67008
67009 osmWay.prototype = Object.create(osmEntity$$1.prototype);
67010
67011
67012 lodash.extend(osmWay.prototype, {
67013     type: 'way',
67014     nodes: [],
67015
67016
67017     copy: function(resolver, copies) {
67018         if (copies[this.id])
67019             return copies[this.id];
67020
67021         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
67022
67023         var nodes = this.nodes.map(function(id) {
67024             return resolver.entity(id).copy(resolver, copies).id;
67025         });
67026
67027         copy = copy.update({ nodes: nodes });
67028         copies[this.id] = copy;
67029
67030         return copy;
67031     },
67032
67033
67034     extent: function(resolver) {
67035         return resolver.transient(this, 'extent', function() {
67036             var extent$$1 = geoExtent$$1();
67037             for (var i = 0; i < this.nodes.length; i++) {
67038                 var node = resolver.hasEntity(this.nodes[i]);
67039                 if (node) {
67040                     extent$$1._extend(node.extent());
67041                 }
67042             }
67043             return extent$$1;
67044         });
67045     },
67046
67047
67048     first: function() {
67049         return this.nodes[0];
67050     },
67051
67052
67053     last: function() {
67054         return this.nodes[this.nodes.length - 1];
67055     },
67056
67057
67058     contains: function(node) {
67059         return this.nodes.indexOf(node) >= 0;
67060     },
67061
67062
67063     affix: function(node) {
67064         if (this.nodes[0] === node) return 'prefix';
67065         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
67066     },
67067
67068
67069     layer: function() {
67070         // explicit layer tag, clamp between -10, 10..
67071         if (isFinite(this.tags.layer)) {
67072             return Math.max(-10, Math.min(+(this.tags.layer), 10));
67073         }
67074
67075         // implied layer tag..
67076         if (this.tags.location === 'overground') return 1;
67077         if (this.tags.location === 'underground') return -1;
67078         if (this.tags.location === 'underwater') return -10;
67079
67080         if (this.tags.power === 'line') return 10;
67081         if (this.tags.power === 'minor_line') return 10;
67082         if (this.tags.aerialway) return 10;
67083         if (this.tags.bridge) return 1;
67084         if (this.tags.cutting) return -1;
67085         if (this.tags.tunnel) return -1;
67086         if (this.tags.waterway) return -1;
67087         if (this.tags.man_made === 'pipeline') return -10;
67088         if (this.tags.boundary) return -10;
67089         return 0;
67090     },
67091
67092
67093     isOneWay: function() {
67094         // explicit oneway tag..
67095         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
67096         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
67097
67098         // implied oneway tag..
67099         for (var key in this.tags) {
67100             if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
67101                 return true;
67102         }
67103         return false;
67104     },
67105
67106
67107     lanes: function() {
67108         return osmLanes(this);
67109     },
67110
67111
67112     isClosed: function() {
67113         return this.nodes.length > 0 && this.first() === this.last();
67114     },
67115
67116
67117     isConvex: function(resolver) {
67118         if (!this.isClosed() || this.isDegenerate()) return null;
67119
67120         var nodes = lodash.uniq(resolver.childNodes(this)),
67121             coords = lodash.map(nodes, 'loc'),
67122             curr = 0, prev = 0;
67123
67124         for (var i = 0; i < coords.length; i++) {
67125             var o = coords[(i+1) % coords.length],
67126                 a = coords[i],
67127                 b = coords[(i+2) % coords.length],
67128                 res = geoCross(o, a, b);
67129
67130             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
67131             if (curr === 0) {
67132                 continue;
67133             } else if (prev && curr !== prev) {
67134                 return false;
67135             }
67136             prev = curr;
67137         }
67138         return true;
67139     },
67140
67141
67142     isArea: function() {
67143         if (this.tags.area === 'yes')
67144             return true;
67145         if (!this.isClosed() || this.tags.area === 'no')
67146             return false;
67147         for (var key in this.tags) {
67148             if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
67149                 return true;
67150             }
67151         }
67152         return false;
67153     },
67154
67155
67156     isDegenerate: function() {
67157         return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
67158     },
67159
67160
67161     areAdjacent: function(n1, n2) {
67162         for (var i = 0; i < this.nodes.length; i++) {
67163             if (this.nodes[i] === n1) {
67164                 if (this.nodes[i - 1] === n2) return true;
67165                 if (this.nodes[i + 1] === n2) return true;
67166             }
67167         }
67168         return false;
67169     },
67170
67171
67172     geometry: function(graph) {
67173         return graph.transient(this, 'geometry', function() {
67174             return this.isArea() ? 'area' : 'line';
67175         });
67176     },
67177
67178
67179     addNode: function(id, index) {
67180         var nodes = this.nodes.slice();
67181         nodes.splice(index === undefined ? nodes.length : index, 0, id);
67182         return this.update({nodes: nodes});
67183     },
67184
67185
67186     updateNode: function(id, index) {
67187         var nodes = this.nodes.slice();
67188         nodes.splice(index, 1, id);
67189         return this.update({nodes: nodes});
67190     },
67191
67192
67193     replaceNode: function(needle, replacement) {
67194         if (this.nodes.indexOf(needle) < 0)
67195             return this;
67196
67197         var nodes = this.nodes.slice();
67198         for (var i = 0; i < nodes.length; i++) {
67199             if (nodes[i] === needle) {
67200                 nodes[i] = replacement;
67201             }
67202         }
67203         return this.update({nodes: nodes});
67204     },
67205
67206
67207     removeNode: function(id) {
67208         var nodes = [];
67209
67210         for (var i = 0; i < this.nodes.length; i++) {
67211             var node = this.nodes[i];
67212             if (node !== id && nodes[nodes.length - 1] !== node) {
67213                 nodes.push(node);
67214             }
67215         }
67216
67217         // Preserve circularity
67218         if (this.nodes.length > 1 && this.first() === id && this.last() === id && nodes[nodes.length - 1] !== nodes[0]) {
67219             nodes.push(nodes[0]);
67220         }
67221
67222         return this.update({nodes: nodes});
67223     },
67224
67225
67226     asJXON: function(changeset_id) {
67227         var r = {
67228             way: {
67229                 '@id': this.osmId(),
67230                 '@version': this.version || 0,
67231                 nd: lodash.map(this.nodes, function(id) {
67232                     return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
67233                 }),
67234                 tag: lodash.map(this.tags, function(v, k) {
67235                     return { keyAttributes: { k: k, v: v } };
67236                 })
67237             }
67238         };
67239         if (changeset_id) r.way['@changeset'] = changeset_id;
67240         return r;
67241     },
67242
67243
67244     asGeoJSON: function(resolver) {
67245         return resolver.transient(this, 'GeoJSON', function() {
67246             var coordinates = lodash.map(resolver.childNodes(this), 'loc');
67247             if (this.isArea() && this.isClosed()) {
67248                 return {
67249                     type: 'Polygon',
67250                     coordinates: [coordinates]
67251                 };
67252             } else {
67253                 return {
67254                     type: 'LineString',
67255                     coordinates: coordinates
67256                 };
67257             }
67258         });
67259     },
67260
67261
67262     area: function(resolver) {
67263         return resolver.transient(this, 'area', function() {
67264             var nodes = resolver.childNodes(this);
67265
67266             var json$$1 = {
67267                 type: 'Polygon',
67268                 coordinates: [lodash.map(nodes, 'loc')]
67269             };
67270
67271             if (!this.isClosed() && nodes.length) {
67272                 json$$1.coordinates[0].push(nodes[0].loc);
67273             }
67274
67275             var area$$1 = area$1(json$$1);
67276
67277             // Heuristic for detecting counterclockwise winding order. Assumes
67278             // that OpenStreetMap polygons are not hemisphere-spanning.
67279             if (area$$1 > 2 * Math.PI) {
67280                 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
67281                 area$$1 = area$1(json$$1);
67282             }
67283
67284             return isNaN(area$$1) ? 0 : area$$1;
67285         });
67286     }
67287 });
67288
67289 function osmTurn(turn) {
67290     if (!(this instanceof osmTurn))
67291         return new osmTurn(turn);
67292     lodash.extend(this, turn);
67293 }
67294
67295
67296 function osmIntersection(graph, vertexId) {
67297     var vertex = graph.entity(vertexId),
67298         parentWays = graph.parentWays(vertex),
67299         coincident = [],
67300         highways = {};
67301
67302     function addHighway(way, adjacentNodeId) {
67303         if (highways[adjacentNodeId]) {
67304             coincident.push(adjacentNodeId);
67305         } else {
67306             highways[adjacentNodeId] = way;
67307         }
67308     }
67309
67310     // Pre-split ways that would need to be split in
67311     // order to add a restriction. The real split will
67312     // happen when the restriction is added.
67313     parentWays.forEach(function(way) {
67314         if (!way.tags.highway || way.isArea() || way.isDegenerate())
67315             return;
67316
67317         var isFirst = (vertexId === way.first()),
67318             isLast = (vertexId === way.last()),
67319             isAffix = (isFirst || isLast),
67320             isClosingNode = (isFirst && isLast);
67321
67322         if (isAffix && !isClosingNode) {
67323             var index = (isFirst ? 1 : way.nodes.length - 2);
67324             addHighway(way, way.nodes[index]);
67325
67326         } else {
67327             var splitIndex, wayA, wayB, indexA, indexB;
67328             if (isClosingNode) {
67329                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
67330                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
67331                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
67332                 indexA = 1;
67333                 indexB = way.nodes.length - 2;
67334             } else {
67335                 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
67336                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
67337                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
67338                 indexA = splitIndex - 1;
67339                 indexB = splitIndex + 1;
67340             }
67341             graph = graph.replace(wayA).replace(wayB);
67342             addHighway(wayA, way.nodes[indexA]);
67343             addHighway(wayB, way.nodes[indexB]);
67344         }
67345     });
67346
67347     // remove any ways from this intersection that are coincident
67348     // (i.e. any adjacent node used by more than one intersecting way)
67349     coincident.forEach(function (n) {
67350         delete highways[n];
67351     });
67352
67353
67354     var intersection = {
67355         highways: highways,
67356         ways: lodash.values(highways),
67357         graph: graph
67358     };
67359
67360
67361     intersection.adjacentNodeId = function(fromWayId) {
67362         return lodash.find(lodash.keys(highways), function(k) {
67363             return highways[k].id === fromWayId;
67364         });
67365     };
67366
67367
67368     intersection.turns = function(fromNodeId) {
67369         var start = highways[fromNodeId];
67370         if (!start)
67371             return [];
67372
67373         if (start.first() === vertex.id && start.tags.oneway === 'yes')
67374             return [];
67375         if (start.last() === vertex.id && start.tags.oneway === '-1')
67376             return [];
67377
67378         function withRestriction(turn) {
67379             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
67380                 if (relation.tags.type !== 'restriction')
67381                     return;
67382
67383                 var f = relation.memberByRole('from'),
67384                     t = relation.memberByRole('to'),
67385                     v = relation.memberByRole('via');
67386
67387                 if (f && f.id === turn.from.way &&
67388                     v && v.id === turn.via.node &&
67389                     t && t.id === turn.to.way) {
67390                     turn.restriction = relation.id;
67391                 } else if (/^only_/.test(relation.tags.restriction) &&
67392                     f && f.id === turn.from.way &&
67393                     v && v.id === turn.via.node &&
67394                     t && t.id !== turn.to.way) {
67395                     turn.restriction = relation.id;
67396                     turn.indirect_restriction = true;
67397                 }
67398             });
67399
67400             return osmTurn(turn);
67401         }
67402
67403
67404         var from = {
67405                 node: fromNodeId,
67406                 way: start.id.split(/-(a|b)/)[0]
67407             },
67408             via = { node: vertex.id },
67409             turns = [];
67410
67411         lodash.each(highways, function(end, adjacentNodeId) {
67412             if (end === start)
67413                 return;
67414
67415             // backward
67416             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
67417                 turns.push(withRestriction({
67418                     from: from,
67419                     via: via,
67420                     to: {
67421                         node: adjacentNodeId,
67422                         way: end.id.split(/-(a|b)/)[0]
67423                     }
67424                 }));
67425             }
67426
67427             // forward
67428             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
67429                 turns.push(withRestriction({
67430                     from: from,
67431                     via: via,
67432                     to: {
67433                         node: adjacentNodeId,
67434                         way: end.id.split(/-(a|b)/)[0]
67435                     }
67436                 }));
67437             }
67438
67439         });
67440
67441         // U-turn
67442         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
67443             turns.push(withRestriction({
67444                 from: from,
67445                 via: via,
67446                 to: from,
67447                 u: true
67448             }));
67449         }
67450
67451         return turns;
67452     };
67453
67454     return intersection;
67455 }
67456
67457
67458 function osmInferRestriction(graph, from, via, to, projection) {
67459     var fromWay = graph.entity(from.way),
67460         fromNode = graph.entity(from.node),
67461         toWay = graph.entity(to.way),
67462         toNode = graph.entity(to.node),
67463         viaNode = graph.entity(via.node),
67464         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
67465             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
67466         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
67467             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
67468         angle = geoAngle(viaNode, fromNode, projection) -
67469                 geoAngle(viaNode, toNode, projection);
67470
67471     angle = angle * 180 / Math.PI;
67472
67473     while (angle < 0)
67474         angle += 360;
67475
67476     if (fromNode === toNode)
67477         return 'no_u_turn';
67478     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
67479         return 'no_u_turn';
67480     if (angle < 158)
67481         return 'no_right_turn';
67482     if (angle > 202)
67483         return 'no_left_turn';
67484
67485     return 'no_straight_on';
67486 }
67487
67488 function actionAddMember(relationId, member, memberIndex) {
67489     return function(graph) {
67490         var relation = graph.entity(relationId);
67491
67492         if (isNaN(memberIndex) && member.type === 'way') {
67493             var members = relation.indexedMembers();
67494             members.push(member);
67495
67496             var joined = osmJoinWays(members, graph);
67497             for (var i = 0; i < joined.length; i++) {
67498                 var segment = joined[i];
67499                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
67500                     if (segment[j] !== member)
67501                         continue;
67502
67503                     if (j === 0) {
67504                         memberIndex = segment[j + 1].index;
67505                     } else if (j === segment.length - 1) {
67506                         memberIndex = segment[j - 1].index + 1;
67507                     } else {
67508                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
67509                     }
67510                 }
67511             }
67512         }
67513
67514         return graph.replace(relation.addMember(member, memberIndex));
67515     };
67516 }
67517
67518 function actionAddMidpoint(midpoint, node) {
67519     return function(graph) {
67520         graph = graph.replace(node.move(midpoint.loc));
67521
67522         var parents = lodash.intersection(
67523             graph.parentWays(graph.entity(midpoint.edge[0])),
67524             graph.parentWays(graph.entity(midpoint.edge[1])));
67525
67526         parents.forEach(function(way) {
67527             for (var i = 0; i < way.nodes.length - 1; i++) {
67528                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
67529                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
67530
67531                     // Add only one midpoint on doubled-back segments,
67532                     // turning them into self-intersections.
67533                     return;
67534                 }
67535             }
67536         });
67537
67538         return graph;
67539     };
67540 }
67541
67542 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
67543 function actionAddVertex(wayId, nodeId, index) {
67544     return function(graph) {
67545         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
67546     };
67547 }
67548
67549 function actionChangeMember(relationId, member, memberIndex) {
67550     return function(graph) {
67551         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
67552     };
67553 }
67554
67555 function actionChangePreset(entityId, oldPreset, newPreset) {
67556     return function(graph) {
67557         var entity = graph.entity(entityId),
67558             geometry = entity.geometry(graph),
67559             tags = entity.tags;
67560
67561         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
67562         if (newPreset) tags = newPreset.applyTags(tags, geometry);
67563
67564         return graph.replace(entity.update({tags: tags}));
67565     };
67566 }
67567
67568 function actionChangeTags(entityId, tags) {
67569     return function(graph) {
67570         var entity = graph.entity(entityId);
67571         return graph.replace(entity.update({tags: tags}));
67572     };
67573 }
67574
67575 function actionCircularize(wayId, projection, maxAngle) {
67576     maxAngle = (maxAngle || 20) * Math.PI / 180;
67577
67578
67579     var action = function(graph) {
67580         var way = graph.entity(wayId);
67581
67582         if (!way.isConvex(graph)) {
67583             graph = action.makeConvex(graph);
67584         }
67585
67586         var nodes = lodash.uniq(graph.childNodes(way)),
67587             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
67588             points = nodes.map(function(n) { return projection(n.loc); }),
67589             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
67590             centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
67591             radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
67592             sign = d3polygonArea(points) > 0 ? 1 : -1,
67593             ids;
67594
67595         // we need atleast two key nodes for the algorithm to work
67596         if (!keyNodes.length) {
67597             keyNodes = [nodes[0]];
67598             keyPoints = [points[0]];
67599         }
67600
67601         if (keyNodes.length === 1) {
67602             var index = nodes.indexOf(keyNodes[0]),
67603                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
67604
67605             keyNodes.push(nodes[oppositeIndex]);
67606             keyPoints.push(points[oppositeIndex]);
67607         }
67608
67609         // key points and nodes are those connected to the ways,
67610         // they are projected onto the circle, inbetween nodes are moved
67611         // to constant intervals between key nodes, extra inbetween nodes are
67612         // added if necessary.
67613         for (var i = 0; i < keyPoints.length; i++) {
67614             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
67615                 startNode = keyNodes[i],
67616                 endNode = keyNodes[nextKeyNodeIndex],
67617                 startNodeIndex = nodes.indexOf(startNode),
67618                 endNodeIndex = nodes.indexOf(endNode),
67619                 numberNewPoints = -1,
67620                 indexRange = endNodeIndex - startNodeIndex,
67621                 distance, totalAngle, eachAngle, startAngle, endAngle,
67622                 angle, loc, node, j,
67623                 inBetweenNodes = [];
67624
67625             if (indexRange < 0) {
67626                 indexRange += nodes.length;
67627             }
67628
67629             // position this key node
67630             distance = geoEuclideanDistance(centroid, keyPoints[i]);
67631             if (distance === 0) { distance = 1e-4; }
67632             keyPoints[i] = [
67633                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
67634                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
67635             graph = graph.replace(keyNodes[i].move(projection.invert(keyPoints[i])));
67636
67637             // figure out the between delta angle we want to match to
67638             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
67639             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
67640             totalAngle = endAngle - startAngle;
67641
67642             // detects looping around -pi/pi
67643             if (totalAngle * sign > 0) {
67644                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
67645             }
67646
67647             do {
67648                 numberNewPoints++;
67649                 eachAngle = totalAngle / (indexRange + numberNewPoints);
67650             } while (Math.abs(eachAngle) > maxAngle);
67651
67652             // move existing points
67653             for (j = 1; j < indexRange; j++) {
67654                 angle = startAngle + j * eachAngle;
67655                 loc = projection.invert([
67656                     centroid[0] + Math.cos(angle)*radius,
67657                     centroid[1] + Math.sin(angle)*radius]);
67658
67659                 node = nodes[(j + startNodeIndex) % nodes.length].move(loc);
67660                 graph = graph.replace(node);
67661             }
67662
67663             // add new inbetween nodes if necessary
67664             for (j = 0; j < numberNewPoints; j++) {
67665                 angle = startAngle + (indexRange + j) * eachAngle;
67666                 loc = projection.invert([
67667                     centroid[0] + Math.cos(angle) * radius,
67668                     centroid[1] + Math.sin(angle) * radius]);
67669
67670                 node = osmNode({loc: loc});
67671                 graph = graph.replace(node);
67672
67673                 nodes.splice(endNodeIndex + j, 0, node);
67674                 inBetweenNodes.push(node.id);
67675             }
67676
67677             // Check for other ways that share these keyNodes..
67678             // If keyNodes are adjacent in both ways,
67679             // we can add inBetween nodes to that shared way too..
67680             if (indexRange === 1 && inBetweenNodes.length) {
67681                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
67682                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
67683                     wayDirection1 = (endIndex1 - startIndex1);
67684                 if (wayDirection1 < -1) { wayDirection1 = 1; }
67685
67686                 /* eslint-disable no-loop-func */
67687                 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
67688                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
67689                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
67690                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
67691                             wayDirection2 = (endIndex2 - startIndex2),
67692                             insertAt = endIndex2;
67693                         if (wayDirection2 < -1) { wayDirection2 = 1; }
67694
67695                         if (wayDirection1 !== wayDirection2) {
67696                             inBetweenNodes.reverse();
67697                             insertAt = startIndex2;
67698                         }
67699                         for (j = 0; j < inBetweenNodes.length; j++) {
67700                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
67701                         }
67702                         graph = graph.replace(sharedWay);
67703                     }
67704                 });
67705                 /* eslint-enable no-loop-func */
67706             }
67707
67708         }
67709
67710         // update the way to have all the new nodes
67711         ids = nodes.map(function(n) { return n.id; });
67712         ids.push(ids[0]);
67713
67714         way = way.update({nodes: ids});
67715         graph = graph.replace(way);
67716
67717         return graph;
67718     };
67719
67720
67721     action.makeConvex = function(graph) {
67722         var way = graph.entity(wayId),
67723             nodes = lodash.uniq(graph.childNodes(way)),
67724             points = nodes.map(function(n) { return projection(n.loc); }),
67725             sign = d3polygonArea(points) > 0 ? 1 : -1,
67726             hull = d3polygonHull(points);
67727
67728         // D3 convex hulls go counterclockwise..
67729         if (sign === -1) {
67730             nodes.reverse();
67731             points.reverse();
67732         }
67733
67734         for (var i = 0; i < hull.length - 1; i++) {
67735             var startIndex = points.indexOf(hull[i]),
67736                 endIndex = points.indexOf(hull[i+1]),
67737                 indexRange = (endIndex - startIndex);
67738
67739             if (indexRange < 0) {
67740                 indexRange += nodes.length;
67741             }
67742
67743             // move interior nodes to the surface of the convex hull..
67744             for (var j = 1; j < indexRange; j++) {
67745                 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
67746                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
67747                 graph = graph.replace(node);
67748             }
67749         }
67750         return graph;
67751     };
67752
67753
67754     action.disabled = function(graph) {
67755         if (!graph.entity(wayId).isClosed())
67756             return 'not_closed';
67757     };
67758
67759
67760     return action;
67761 }
67762
67763 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
67764 function actionDeleteWay(wayId) {
67765
67766
67767     function canDeleteNode(node, graph) {
67768         return !graph.parentWays(node).length &&
67769             !graph.parentRelations(node).length &&
67770             !node.hasInterestingTags();
67771     }
67772
67773
67774     var action = function(graph) {
67775         var way = graph.entity(wayId);
67776
67777         graph.parentRelations(way)
67778             .forEach(function(parent) {
67779                 parent = parent.removeMembersWithID(wayId);
67780                 graph = graph.replace(parent);
67781
67782                 if (parent.isDegenerate()) {
67783                     graph = actionDeleteRelation(parent.id)(graph);
67784                 }
67785             });
67786
67787         lodash.uniq(way.nodes).forEach(function(nodeId) {
67788             graph = graph.replace(way.removeNode(nodeId));
67789
67790             var node = graph.entity(nodeId);
67791             if (canDeleteNode(node, graph)) {
67792                 graph = graph.remove(node);
67793             }
67794         });
67795
67796         return graph.remove(way);
67797     };
67798
67799
67800     action.disabled = function(graph) {
67801         var disabled = false;
67802
67803         graph.parentRelations(graph.entity(wayId)).forEach(function(parent) {
67804             var type = parent.tags.type,
67805                 role = parent.memberById(wayId).role || 'outer';
67806             if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
67807                 disabled = 'part_of_relation';
67808             }
67809         });
67810
67811         return disabled;
67812     };
67813
67814
67815     return action;
67816 }
67817
67818 function actionDeleteMultiple(ids) {
67819     var actions = {
67820         way: actionDeleteWay,
67821         node: actionDeleteNode,
67822         relation: actionDeleteRelation
67823     };
67824
67825
67826     var action = function(graph) {
67827         ids.forEach(function(id) {
67828             if (graph.hasEntity(id)) { // It may have been deleted aready.
67829                 graph = actions[graph.entity(id).type](id)(graph);
67830             }
67831         });
67832
67833         return graph;
67834     };
67835
67836
67837     action.disabled = function(graph) {
67838         for (var i = 0; i < ids.length; i++) {
67839             var id = ids[i],
67840                 disabled = actions[graph.entity(id).type](id).disabled(graph);
67841             if (disabled) return disabled;
67842         }
67843     };
67844
67845
67846     return action;
67847 }
67848
67849 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
67850 function actionDeleteRelation(relationId) {
67851
67852
67853     function canDeleteEntity(entity, graph) {
67854         return !graph.parentWays(entity).length &&
67855             !graph.parentRelations(entity).length &&
67856             !entity.hasInterestingTags();
67857     }
67858
67859
67860     var action = function(graph) {
67861         var relation = graph.entity(relationId);
67862
67863         graph.parentRelations(relation)
67864             .forEach(function(parent) {
67865                 parent = parent.removeMembersWithID(relationId);
67866                 graph = graph.replace(parent);
67867
67868                 if (parent.isDegenerate()) {
67869                     graph = actionDeleteRelation(parent.id)(graph);
67870                 }
67871             });
67872
67873         lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
67874             graph = graph.replace(relation.removeMembersWithID(memberId));
67875
67876             var entity = graph.entity(memberId);
67877             if (canDeleteEntity(entity, graph)) {
67878                 graph = actionDeleteMultiple([memberId])(graph);
67879             }
67880         });
67881
67882         return graph.remove(relation);
67883     };
67884
67885
67886     action.disabled = function(graph) {
67887         if (!graph.entity(relationId).isComplete(graph))
67888             return 'incomplete_relation';
67889     };
67890
67891
67892     return action;
67893 }
67894
67895 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
67896 function actionDeleteNode(nodeId) {
67897     var action = function(graph) {
67898         var node = graph.entity(nodeId);
67899
67900         graph.parentWays(node)
67901             .forEach(function(parent) {
67902                 parent = parent.removeNode(nodeId);
67903                 graph = graph.replace(parent);
67904
67905                 if (parent.isDegenerate()) {
67906                     graph = actionDeleteWay(parent.id)(graph);
67907                 }
67908             });
67909
67910         graph.parentRelations(node)
67911             .forEach(function(parent) {
67912                 parent = parent.removeMembersWithID(nodeId);
67913                 graph = graph.replace(parent);
67914
67915                 if (parent.isDegenerate()) {
67916                     graph = actionDeleteRelation(parent.id)(graph);
67917                 }
67918             });
67919
67920         return graph.remove(node);
67921     };
67922
67923
67924     action.disabled = function() {
67925         return false;
67926     };
67927
67928
67929     return action;
67930 }
67931
67932 // Connect the ways at the given nodes.
67933 //
67934 // The last node will survive. All other nodes will be replaced with
67935 // the surviving node in parent ways, and then removed.
67936 //
67937 // Tags and relation memberships of of non-surviving nodes are merged
67938 // to the survivor.
67939 //
67940 // This is the inverse of `iD.actionDisconnect`.
67941 //
67942 // Reference:
67943 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
67944 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
67945 //
67946 function actionConnect(nodeIds) {
67947     return function(graph) {
67948         var survivor = graph.entity(lodash.last(nodeIds));
67949
67950         for (var i = 0; i < nodeIds.length - 1; i++) {
67951             var node = graph.entity(nodeIds[i]);
67952
67953             /* eslint-disable no-loop-func */
67954             graph.parentWays(node).forEach(function(parent) {
67955                 if (!parent.areAdjacent(node.id, survivor.id)) {
67956                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
67957                 }
67958             });
67959
67960             graph.parentRelations(node).forEach(function(parent) {
67961                 graph = graph.replace(parent.replaceMember(node, survivor));
67962             });
67963             /* eslint-enable no-loop-func */
67964
67965             survivor = survivor.mergeTags(node.tags);
67966             graph = actionDeleteNode(node.id)(graph);
67967         }
67968
67969         graph = graph.replace(survivor);
67970
67971         return graph;
67972     };
67973 }
67974
67975 function actionCopyEntities(ids, fromGraph) {
67976     var copies = {};
67977
67978
67979     var action = function(graph) {
67980         ids.forEach(function(id) {
67981             fromGraph.entity(id).copy(fromGraph, copies);
67982         });
67983
67984         for (var id in copies) {
67985             graph = graph.replace(copies[id]);
67986         }
67987
67988         return graph;
67989     };
67990
67991
67992     action.copies = function() {
67993         return copies;
67994     };
67995
67996
67997     return action;
67998 }
67999
68000 function actionDeleteMember(relationId, memberIndex) {
68001     return function(graph) {
68002         var relation = graph.entity(relationId)
68003             .removeMember(memberIndex);
68004
68005         graph = graph.replace(relation);
68006
68007         if (relation.isDegenerate())
68008             graph = actionDeleteRelation(relation.id)(graph);
68009
68010         return graph;
68011     };
68012 }
68013
68014 function actionDeprecateTags(entityId) {
68015
68016     return function(graph) {
68017         var entity = graph.entity(entityId),
68018             newtags = lodash.clone(entity.tags),
68019             change = false,
68020             rule;
68021
68022         // This handles dataDeprecated tags with a single condition
68023         for (var i = 0; i < dataDeprecated.length; i++) {
68024
68025             rule = dataDeprecated[i];
68026             var match = lodash.toPairs(rule.old)[0],
68027                 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
68028
68029             if (entity.tags[match[0]] && match[1] === '*') {
68030
68031                 var value = entity.tags[match[0]];
68032                 if (replacements && !newtags[replacements[0][0]]) {
68033                     newtags[replacements[0][0]] = value;
68034                 }
68035                 delete newtags[match[0]];
68036                 change = true;
68037
68038             } else if (entity.tags[match[0]] === match[1]) {
68039                 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
68040                 change = true;
68041             }
68042         }
68043
68044         if (change) {
68045             return graph.replace(entity.update({tags: newtags}));
68046         } else {
68047             return graph;
68048         }
68049     };
68050 }
68051
68052 function actionDiscardTags(difference) {
68053
68054     return function(graph) {
68055         function discardTags(entity) {
68056             if (!lodash.isEmpty(entity.tags)) {
68057                 var tags = {};
68058                 lodash.each(entity.tags, function(v, k) {
68059                     if (v) tags[k] = v;
68060                 });
68061
68062                 graph = graph.replace(entity.update({
68063                     tags: lodash.omit(tags, dataDiscarded)
68064                 }));
68065             }
68066         }
68067
68068         difference.modified().forEach(discardTags);
68069         difference.created().forEach(discardTags);
68070
68071         return graph;
68072     };
68073 }
68074
68075 // Disconect the ways at the given node.
68076 //
68077 // Optionally, disconnect only the given ways.
68078 //
68079 // For testing convenience, accepts an ID to assign to the (first) new node.
68080 // Normally, this will be undefined and the way will automatically
68081 // be assigned a new ID.
68082 //
68083 // This is the inverse of `iD.actionConnect`.
68084 //
68085 // Reference:
68086 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
68087 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
68088 //
68089 function actionDisconnect(nodeId, newNodeId) {
68090     var wayIds;
68091
68092
68093     var action = function(graph) {
68094         var node = graph.entity(nodeId),
68095             connections = action.connections(graph);
68096
68097         connections.forEach(function(connection) {
68098             var way = graph.entity(connection.wayID),
68099                 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
68100
68101             graph = graph.replace(newNode);
68102             if (connection.index === 0 && way.isArea()) {
68103                 // replace shared node with shared node..
68104                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
68105             } else {
68106                 // replace shared node with multiple new nodes..
68107                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
68108             }
68109         });
68110
68111         return graph;
68112     };
68113
68114
68115     action.connections = function(graph) {
68116         var candidates = [],
68117             keeping = false,
68118             parentWays = graph.parentWays(graph.entity(nodeId));
68119
68120         parentWays.forEach(function(way) {
68121             if (wayIds && wayIds.indexOf(way.id) === -1) {
68122                 keeping = true;
68123                 return;
68124             }
68125             if (way.isArea() && (way.nodes[0] === nodeId)) {
68126                 candidates.push({wayID: way.id, index: 0});
68127             } else {
68128                 way.nodes.forEach(function(waynode, index) {
68129                     if (waynode === nodeId) {
68130                         candidates.push({wayID: way.id, index: index});
68131                     }
68132                 });
68133             }
68134         });
68135
68136         return keeping ? candidates : candidates.slice(1);
68137     };
68138
68139
68140     action.disabled = function(graph) {
68141         var connections = action.connections(graph);
68142         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
68143             return 'not_connected';
68144
68145         var parentWays = graph.parentWays(graph.entity(nodeId)),
68146             seenRelationIds = {},
68147             sharedRelation;
68148
68149         parentWays.forEach(function(way) {
68150             if (wayIds && wayIds.indexOf(way.id) === -1)
68151                 return;
68152
68153             var relations = graph.parentRelations(way);
68154             relations.forEach(function(relation) {
68155                 if (relation.id in seenRelationIds) {
68156                     sharedRelation = relation;
68157                 } else {
68158                     seenRelationIds[relation.id] = true;
68159                 }
68160             });
68161         });
68162
68163         if (sharedRelation)
68164             return 'relation';
68165     };
68166
68167
68168     action.limitWays = function(_) {
68169         if (!arguments.length) return wayIds;
68170         wayIds = _;
68171         return action;
68172     };
68173
68174
68175     return action;
68176 }
68177
68178 // Join ways at the end node they share.
68179 //
68180 // This is the inverse of `iD.actionSplit`.
68181 //
68182 // Reference:
68183 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
68184 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
68185 //
68186 function actionJoin(ids) {
68187
68188     function groupEntitiesByGeometry(graph) {
68189         var entities = ids.map(function(id) { return graph.entity(id); });
68190         return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
68191     }
68192
68193
68194     var action = function(graph) {
68195         var ways = ids.map(graph.entity, graph),
68196             survivor = ways[0];
68197
68198         // Prefer to keep an existing way.
68199         for (var i = 0; i < ways.length; i++) {
68200             if (!ways[i].isNew()) {
68201                 survivor = ways[i];
68202                 break;
68203             }
68204         }
68205
68206         var joined = osmJoinWays(ways, graph)[0];
68207
68208         survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
68209         graph = graph.replace(survivor);
68210
68211         joined.forEach(function(way) {
68212             if (way.id === survivor.id)
68213                 return;
68214
68215             graph.parentRelations(way).forEach(function(parent) {
68216                 graph = graph.replace(parent.replaceMember(way, survivor));
68217             });
68218
68219             survivor = survivor.mergeTags(way.tags);
68220
68221             graph = graph.replace(survivor);
68222             graph = actionDeleteWay(way.id)(graph);
68223         });
68224
68225         return graph;
68226     };
68227
68228
68229     action.disabled = function(graph) {
68230         var geometries = groupEntitiesByGeometry(graph);
68231         if (ids.length < 2 || ids.length !== geometries.line.length)
68232             return 'not_eligible';
68233
68234         var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
68235         if (joined.length > 1)
68236             return 'not_adjacent';
68237
68238         var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
68239             relation,
68240             tags = {},
68241             conflicting = false;
68242
68243         joined[0].forEach(function(way) {
68244             var parents = graph.parentRelations(way);
68245             parents.forEach(function(parent) {
68246                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
68247                     relation = parent;
68248             });
68249
68250             for (var k in way.tags) {
68251                 if (!(k in tags)) {
68252                     tags[k] = way.tags[k];
68253                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
68254                     conflicting = true;
68255                 }
68256             }
68257         });
68258
68259         if (relation)
68260             return 'restriction';
68261
68262         if (conflicting)
68263             return 'conflicting_tags';
68264     };
68265
68266
68267     return action;
68268 }
68269
68270 function actionMerge(ids) {
68271
68272     function groupEntitiesByGeometry(graph) {
68273         var entities = ids.map(function(id) { return graph.entity(id); });
68274         return lodash.extend({point: [], area: [], line: [], relation: []},
68275             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
68276     }
68277
68278
68279     var action = function(graph) {
68280         var geometries = groupEntitiesByGeometry(graph),
68281             target = geometries.area[0] || geometries.line[0],
68282             points = geometries.point;
68283
68284         points.forEach(function(point) {
68285             target = target.mergeTags(point.tags);
68286
68287             graph.parentRelations(point).forEach(function(parent) {
68288                 graph = graph.replace(parent.replaceMember(point, target));
68289             });
68290
68291             graph = graph.remove(point);
68292         });
68293
68294         graph = graph.replace(target);
68295
68296         return graph;
68297     };
68298
68299
68300     action.disabled = function(graph) {
68301         var geometries = groupEntitiesByGeometry(graph);
68302         if (geometries.point.length === 0 ||
68303             (geometries.area.length + geometries.line.length) !== 1 ||
68304             geometries.relation.length !== 0)
68305             return 'not_eligible';
68306     };
68307
68308
68309     return action;
68310 }
68311
68312 function actionMergePolygon(ids, newRelationId) {
68313
68314     function groupEntities(graph) {
68315         var entities = ids.map(function (id) { return graph.entity(id); });
68316         return lodash.extend({
68317                 closedWay: [],
68318                 multipolygon: [],
68319                 other: []
68320             }, lodash.groupBy(entities, function(entity) {
68321                 if (entity.type === 'way' && entity.isClosed()) {
68322                     return 'closedWay';
68323                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
68324                     return 'multipolygon';
68325                 } else {
68326                     return 'other';
68327                 }
68328             }));
68329     }
68330
68331
68332     var action = function(graph) {
68333         var entities = groupEntities(graph);
68334
68335         // An array representing all the polygons that are part of the multipolygon.
68336         //
68337         // Each element is itself an array of objects with an id property, and has a
68338         // locs property which is an array of the locations forming the polygon.
68339         var polygons = entities.multipolygon.reduce(function(polygons, m) {
68340             return polygons.concat(osmJoinWays(m.members, graph));
68341         }, []).concat(entities.closedWay.map(function(d) {
68342             var member = [{id: d.id}];
68343             member.nodes = graph.childNodes(d);
68344             return member;
68345         }));
68346
68347         // contained is an array of arrays of boolean values,
68348         // where contained[j][k] is true iff the jth way is
68349         // contained by the kth way.
68350         var contained = polygons.map(function(w, i) {
68351             return polygons.map(function(d, n) {
68352                 if (i === n) return null;
68353                 return geoPolygonContainsPolygon(
68354                     lodash.map(d.nodes, 'loc'),
68355                     lodash.map(w.nodes, 'loc'));
68356             });
68357         });
68358
68359         // Sort all polygons as either outer or inner ways
68360         var members = [],
68361             outer = true;
68362
68363         while (polygons.length) {
68364             extractUncontained(polygons);
68365             polygons = polygons.filter(isContained);
68366             contained = contained.filter(isContained).map(filterContained);
68367         }
68368
68369         function isContained(d, i) {
68370             return lodash.some(contained[i]);
68371         }
68372
68373         function filterContained(d) {
68374             return d.filter(isContained);
68375         }
68376
68377         function extractUncontained(polygons) {
68378             polygons.forEach(function(d, i) {
68379                 if (!isContained(d, i)) {
68380                     d.forEach(function(member) {
68381                         members.push({
68382                             type: 'way',
68383                             id: member.id,
68384                             role: outer ? 'outer' : 'inner'
68385                         });
68386                     });
68387                 }
68388             });
68389             outer = !outer;
68390         }
68391
68392         // Move all tags to one relation
68393         var relation = entities.multipolygon[0] ||
68394             osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
68395
68396         entities.multipolygon.slice(1).forEach(function(m) {
68397             relation = relation.mergeTags(m.tags);
68398             graph = graph.remove(m);
68399         });
68400
68401         entities.closedWay.forEach(function(way) {
68402             function isThisOuter(m) {
68403                 return m.id === way.id && m.role !== 'inner';
68404             }
68405             if (members.some(isThisOuter)) {
68406                 relation = relation.mergeTags(way.tags);
68407                 graph = graph.replace(way.update({ tags: {} }));
68408             }
68409         });
68410
68411         return graph.replace(relation.update({
68412             members: members,
68413             tags: lodash.omit(relation.tags, 'area')
68414         }));
68415     };
68416
68417
68418     action.disabled = function(graph) {
68419         var entities = groupEntities(graph);
68420         if (entities.other.length > 0 ||
68421             entities.closedWay.length + entities.multipolygon.length < 2)
68422             return 'not_eligible';
68423         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
68424             return 'incomplete_relation';
68425     };
68426
68427
68428     return action;
68429 }
68430
68431 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
68432 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
68433 //
68434 // Permission is hereby granted, free of charge, to any person
68435 // obtaining a copy of this software and associated documentation files
68436 // (the "Software"), to deal in the Software without restriction,
68437 // including without limitation the rights to use, copy, modify, merge,
68438 // publish, distribute, sublicense, and/or sell copies of the Software,
68439 // and to permit persons to whom the Software is furnished to do so,
68440 // subject to the following conditions:
68441 //
68442 // The above copyright notice and this permission notice shall be
68443 // included in all copies or substantial portions of the Software.
68444 //
68445 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
68446 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68447 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
68448 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
68449 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
68450 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
68451 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
68452 // SOFTWARE.
68453
68454 // source:  https://bitbucket.org/lshift/synchrotron/src
68455 function longest_common_subsequence(file1, file2) {
68456     /* Text diff algorithm following Hunt and McIlroy 1976.
68457      * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
68458      * comparison, Bell Telephone Laboratories CSTR #41 (1976)
68459      * http://www.cs.dartmouth.edu/~doug/
68460      *
68461      * Expects two arrays of strings.
68462      */
68463     var equivalenceClasses;
68464     var file2indices;
68465     var newCandidate;
68466     var candidates;
68467     var line;
68468     var c, i, j, jX, r, s;
68469
68470     equivalenceClasses = {};
68471     for (j = 0; j < file2.length; j++) {
68472         line = file2[j];
68473         if (equivalenceClasses[line]) {
68474             equivalenceClasses[line].push(j);
68475         } else {
68476             equivalenceClasses[line] = [j];
68477         }
68478     }
68479
68480     candidates = [{file1index: -1,
68481                    file2index: -1,
68482                    chain: null}];
68483
68484     for (i = 0; i < file1.length; i++) {
68485         line = file1[i];
68486         file2indices = equivalenceClasses[line] || [];
68487
68488         r = 0;
68489         c = candidates[0];
68490
68491         for (jX = 0; jX < file2indices.length; jX++) {
68492             j = file2indices[jX];
68493
68494             for (s = 0; s < candidates.length; s++) {
68495                 if ((candidates[s].file2index < j) &&
68496                     ((s === candidates.length - 1) ||
68497                      (candidates[s + 1].file2index > j)))
68498                     break;
68499             }
68500
68501             if (s < candidates.length) {
68502                 newCandidate = {file1index: i,
68503                                 file2index: j,
68504                                 chain: candidates[s]};
68505                 if (r === candidates.length) {
68506                     candidates.push(c);
68507                 } else {
68508                     candidates[r] = c;
68509                 }
68510                 r = s + 1;
68511                 c = newCandidate;
68512                 if (r === candidates.length) {
68513                     break; // no point in examining further (j)s
68514                 }
68515             }
68516         }
68517
68518         candidates[r] = c;
68519     }
68520
68521     // At this point, we know the LCS: it's in the reverse of the
68522     // linked-list through .chain of
68523     // candidates[candidates.length - 1].
68524
68525     return candidates[candidates.length - 1];
68526 }
68527
68528
68529
68530
68531
68532
68533
68534
68535
68536
68537
68538 function diff_indices(file1, file2) {
68539     // We apply the LCS to give a simple representation of the
68540     // offsets and lengths of mismatched chunks in the input
68541     // files. This is used by diff3_merge_indices below.
68542
68543     var result = [];
68544     var tail1 = file1.length;
68545     var tail2 = file2.length;
68546
68547     for (var candidate = longest_common_subsequence(file1, file2);
68548          candidate !== null;
68549          candidate = candidate.chain)
68550     {
68551         var mismatchLength1 = tail1 - candidate.file1index - 1;
68552         var mismatchLength2 = tail2 - candidate.file2index - 1;
68553         tail1 = candidate.file1index;
68554         tail2 = candidate.file2index;
68555
68556         if (mismatchLength1 || mismatchLength2) {
68557             result.push({file1: [tail1 + 1, mismatchLength1],
68558                          file2: [tail2 + 1, mismatchLength2]});
68559         }
68560     }
68561
68562     result.reverse();
68563     return result;
68564 }
68565
68566 function diff3_merge_indices (a, o, b) {
68567     // Given three files, A, O, and B, where both A and B are
68568     // independently derived from O, returns a fairly complicated
68569     // internal representation of merge decisions it's taken. The
68570     // interested reader may wish to consult
68571     //
68572     // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
68573     // Formal Investigation of Diff3." In Arvind and Prasad,
68574     // editors, Foundations of Software Technology and Theoretical
68575     // Computer Science (FSTTCS), December 2007.
68576     //
68577     // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
68578     var i;
68579
68580     var m1 = diff_indices(o, a);
68581     var m2 = diff_indices(o, b);
68582
68583     var hunks = [];
68584     function addHunk(h, side) {
68585         hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
68586     }
68587     for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
68588     for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
68589     hunks.sort();
68590
68591     var result = [];
68592     var commonOffset = 0;
68593     function copyCommon(targetOffset) {
68594         if (targetOffset > commonOffset) {
68595             result.push([1, commonOffset, targetOffset - commonOffset]);
68596             commonOffset = targetOffset;
68597         }
68598     }
68599
68600     for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
68601         var firstHunkIndex = hunkIndex;
68602         var hunk = hunks[hunkIndex];
68603         var regionLhs = hunk[0];
68604         var regionRhs = regionLhs + hunk[2];
68605         while (hunkIndex < hunks.length - 1) {
68606             var maybeOverlapping = hunks[hunkIndex + 1];
68607             var maybeLhs = maybeOverlapping[0];
68608             if (maybeLhs > regionRhs) break;
68609             regionRhs = maybeLhs + maybeOverlapping[2];
68610             hunkIndex++;
68611         }
68612
68613         copyCommon(regionLhs);
68614         if (firstHunkIndex === hunkIndex) {
68615     // The "overlap" was only one hunk long, meaning that
68616     // there's no conflict here. Either a and o were the
68617     // same, or b and o were the same.
68618             if (hunk[4] > 0) {
68619                 result.push([hunk[1], hunk[3], hunk[4]]);
68620             }
68621         } else {
68622     // A proper conflict. Determine the extents of the
68623     // regions involved from a, o and b. Effectively merge
68624     // all the hunks on the left into one giant hunk, and
68625     // do the same for the right; then, correct for skew
68626     // in the regions of o that each side changed, and
68627     // report appropriate spans for the three sides.
68628     var regions = {
68629         0: [a.length, -1, o.length, -1],
68630         2: [b.length, -1, o.length, -1]
68631     };
68632             for (i = firstHunkIndex; i <= hunkIndex; i++) {
68633         hunk = hunks[i];
68634                 var side = hunk[1];
68635         var r = regions[side];
68636         var oLhs = hunk[0];
68637         var oRhs = oLhs + hunk[2];
68638                 var abLhs = hunk[3];
68639                 var abRhs = abLhs + hunk[4];
68640         r[0] = Math.min(abLhs, r[0]);
68641         r[1] = Math.max(abRhs, r[1]);
68642         r[2] = Math.min(oLhs, r[2]);
68643         r[3] = Math.max(oRhs, r[3]);
68644             }
68645     var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
68646     var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
68647     var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
68648     var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
68649             result.push([-1,
68650              aLhs,      aRhs      - aLhs,
68651              regionLhs, regionRhs - regionLhs,
68652              bLhs,      bRhs      - bLhs]);
68653         }
68654         commonOffset = regionRhs;
68655     }
68656
68657     copyCommon(o.length);
68658     return result;
68659 }
68660
68661 function diff3_merge (a, o, b, excludeFalseConflicts) {
68662     // Applies the output of Diff3.diff3_merge_indices to actually
68663     // construct the merged file; the returned result alternates
68664     // between "ok" and "conflict" blocks.
68665
68666     var result = [];
68667     var files = [a, o, b];
68668     var indices = diff3_merge_indices(a, o, b);
68669
68670     var okLines = [];
68671     function flushOk() {
68672         if (okLines.length) {
68673             result.push({ok: okLines});
68674         }
68675         okLines = [];
68676     }
68677     function pushOk(xs) {
68678         for (var j = 0; j < xs.length; j++) {
68679             okLines.push(xs[j]);
68680         }
68681     }
68682
68683     function isTrueConflict(rec) {
68684         if (rec[2] !== rec[6]) return true;
68685         var aoff = rec[1];
68686         var boff = rec[5];
68687         for (var j = 0; j < rec[2]; j++) {
68688             if (a[j + aoff] !== b[j + boff]) return true;
68689         }
68690         return false;
68691     }
68692
68693     for (var i = 0; i < indices.length; i++) {
68694         var x = indices[i];
68695         var side = x[0];
68696         if (side === -1) {
68697             if (excludeFalseConflicts && !isTrueConflict(x)) {
68698                 pushOk(files[0].slice(x[1], x[1] + x[2]));
68699             } else {
68700                 flushOk();
68701                 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
68702                                         aIndex: x[1],
68703                                         o: o.slice(x[3], x[3] + x[4]),
68704                                         oIndex: x[3],
68705                                         b: b.slice(x[5], x[5] + x[6]),
68706                                         bIndex: x[5]}});
68707             }
68708         } else {
68709             pushOk(files[side].slice(x[1], x[1] + x[2]));
68710         }
68711     }
68712
68713     flushOk();
68714     return result;
68715 }
68716
68717 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
68718     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
68719         conflicts = [];
68720
68721
68722     function user(d) {
68723         return lodash.isFunction(formatUser) ? formatUser(d) : d;
68724     }
68725
68726
68727     function mergeLocation(remote, target) {
68728         function pointEqual(a, b) {
68729             var epsilon = 1e-6;
68730             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
68731         }
68732
68733         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
68734             return target;
68735         }
68736         if (option === 'force_remote') {
68737             return target.update({loc: remote.loc});
68738         }
68739
68740         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
68741         return target;
68742     }
68743
68744
68745     function mergeNodes(base, remote, target) {
68746         if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
68747             return target;
68748         }
68749         if (option === 'force_remote') {
68750             return target.update({nodes: remote.nodes});
68751         }
68752
68753         var ccount = conflicts.length,
68754             o = base.nodes || [],
68755             a = target.nodes || [],
68756             b = remote.nodes || [],
68757             nodes = [],
68758             hunks = diff3_merge(a, o, b, true);
68759
68760         for (var i = 0; i < hunks.length; i++) {
68761             var hunk = hunks[i];
68762             if (hunk.ok) {
68763                 nodes.push.apply(nodes, hunk.ok);
68764             } else {
68765                 // for all conflicts, we can assume c.a !== c.b
68766                 // because `diff3_merge` called with `true` option to exclude false conflicts..
68767                 var c = hunk.conflict;
68768                 if (lodash.isEqual(c.o, c.a)) {  // only changed remotely
68769                     nodes.push.apply(nodes, c.b);
68770                 } else if (lodash.isEqual(c.o, c.b)) {  // only changed locally
68771                     nodes.push.apply(nodes, c.a);
68772                 } else {       // changed both locally and remotely
68773                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
68774                     break;
68775                 }
68776             }
68777         }
68778
68779         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
68780     }
68781
68782
68783     function mergeChildren(targetWay, children, updates, graph) {
68784         function isUsed(node, targetWay) {
68785             var parentWays = lodash.map(graph.parentWays(node), 'id');
68786             return node.hasInterestingTags() ||
68787                 lodash.without(parentWays, targetWay.id).length > 0 ||
68788                 graph.parentRelations(node).length > 0;
68789         }
68790
68791         var ccount = conflicts.length;
68792
68793         for (var i = 0; i < children.length; i++) {
68794             var id = children[i],
68795                 node = graph.hasEntity(id);
68796
68797             // remove unused childNodes..
68798             if (targetWay.nodes.indexOf(id) === -1) {
68799                 if (node && !isUsed(node, targetWay)) {
68800                     updates.removeIds.push(id);
68801                 }
68802                 continue;
68803             }
68804
68805             // restore used childNodes..
68806             var local = localGraph.hasEntity(id),
68807                 remote = remoteGraph.hasEntity(id),
68808                 target;
68809
68810             if (option === 'force_remote' && remote && remote.visible) {
68811                 updates.replacements.push(remote);
68812
68813             } else if (option === 'force_local' && local) {
68814                 target = osmEntity$$1(local);
68815                 if (remote) {
68816                     target = target.update({ version: remote.version });
68817                 }
68818                 updates.replacements.push(target);
68819
68820             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
68821                 target = osmEntity$$1(local, { version: remote.version });
68822                 if (remote.visible) {
68823                     target = mergeLocation(remote, target);
68824                 } else {
68825                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
68826                 }
68827
68828                 if (conflicts.length !== ccount) break;
68829                 updates.replacements.push(target);
68830             }
68831         }
68832
68833         return targetWay;
68834     }
68835
68836
68837     function updateChildren(updates, graph) {
68838         for (var i = 0; i < updates.replacements.length; i++) {
68839             graph = graph.replace(updates.replacements[i]);
68840         }
68841         if (updates.removeIds.length) {
68842             graph = actionDeleteMultiple(updates.removeIds)(graph);
68843         }
68844         return graph;
68845     }
68846
68847
68848     function mergeMembers(remote, target) {
68849         if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
68850             return target;
68851         }
68852         if (option === 'force_remote') {
68853             return target.update({members: remote.members});
68854         }
68855
68856         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
68857         return target;
68858     }
68859
68860
68861     function mergeTags(base, remote, target) {
68862         function ignoreKey(k) {
68863             return lodash.includes(dataDiscarded, k);
68864         }
68865
68866         if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
68867             return target;
68868         }
68869         if (option === 'force_remote') {
68870             return target.update({tags: remote.tags});
68871         }
68872
68873         var ccount = conflicts.length,
68874             o = base.tags || {},
68875             a = target.tags || {},
68876             b = remote.tags || {},
68877             keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
68878             tags = lodash.clone(a),
68879             changed = false;
68880
68881         for (var i = 0; i < keys.length; i++) {
68882             var k = keys[i];
68883
68884             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
68885                 if (o[k] !== a[k]) {      // changed locally..
68886                     conflicts.push(t('merge_remote_changes.conflict.tags',
68887                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
68888
68889                 } else {                  // unchanged locally, accept remote change..
68890                     if (b.hasOwnProperty(k)) {
68891                         tags[k] = b[k];
68892                     } else {
68893                         delete tags[k];
68894                     }
68895                     changed = true;
68896                 }
68897             }
68898         }
68899
68900         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
68901     }
68902
68903
68904     //  `graph.base()` is the common ancestor of the two graphs.
68905     //  `localGraph` contains user's edits up to saving
68906     //  `remoteGraph` contains remote edits to modified nodes
68907     //  `graph` must be a descendent of `localGraph` and may include
68908     //      some conflict resolution actions performed on it.
68909     //
68910     //                  --- ... --- `localGraph` -- ... -- `graph`
68911     //                 /
68912     //  `graph.base()` --- ... --- `remoteGraph`
68913     //
68914     var action = function(graph) {
68915         var updates = { replacements: [], removeIds: [] },
68916             base = graph.base().entities[id],
68917             local = localGraph.entity(id),
68918             remote = remoteGraph.entity(id),
68919             target = osmEntity$$1(local, { version: remote.version });
68920
68921         // delete/undelete
68922         if (!remote.visible) {
68923             if (option === 'force_remote') {
68924                 return actionDeleteMultiple([id])(graph);
68925
68926             } else if (option === 'force_local') {
68927                 if (target.type === 'way') {
68928                     target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
68929                     graph = updateChildren(updates, graph);
68930                 }
68931                 return graph.replace(target);
68932
68933             } else {
68934                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
68935                 return graph;  // do nothing
68936             }
68937         }
68938
68939         // merge
68940         if (target.type === 'node') {
68941             target = mergeLocation(remote, target);
68942
68943         } else if (target.type === 'way') {
68944             // pull in any child nodes that may not be present locally..
68945             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
68946             target = mergeNodes(base, remote, target);
68947             target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
68948
68949         } else if (target.type === 'relation') {
68950             target = mergeMembers(remote, target);
68951         }
68952
68953         target = mergeTags(base, remote, target);
68954
68955         if (!conflicts.length) {
68956             graph = updateChildren(updates, graph).replace(target);
68957         }
68958
68959         return graph;
68960     };
68961
68962
68963     action.withOption = function(opt) {
68964         option = opt;
68965         return action;
68966     };
68967
68968
68969     action.conflicts = function() {
68970         return conflicts;
68971     };
68972
68973
68974     return action;
68975 }
68976
68977 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
68978 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
68979 function actionMove(moveIds, tryDelta, projection, cache) {
68980     var delta = tryDelta;
68981
68982     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
68983     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
68984
68985     function setupCache(graph) {
68986         function canMove(nodeId) {
68987             // Allow movement of any node that is in the selectedIDs list..
68988             if (moveIds.indexOf(nodeId) !== -1) return true;
68989
68990             // Allow movement of a vertex where 2 ways meet..
68991             var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
68992             if (parents.length < 3) return true;
68993
68994             // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
68995             var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
68996             if (!parentsMoving) delete cache.moving[nodeId];
68997
68998             return parentsMoving;
68999         }
69000
69001         function cacheEntities(ids) {
69002             ids.forEach(function(id) {
69003                 if (cache.moving[id]) return;
69004                 cache.moving[id] = true;
69005
69006                 var entity = graph.hasEntity(id);
69007                 if (!entity) return;
69008
69009                 if (entity.type === 'node') {
69010                     cache.nodes.push(id);
69011                     cache.startLoc[id] = entity.loc;
69012                 } else if (entity.type === 'way') {
69013                     cache.ways.push(id);
69014                     cacheEntities(entity.nodes);
69015                 } else {
69016                     cacheEntities(entity.members.map(function(member) {
69017                         return member.id;
69018                     }));
69019                 }
69020             });
69021         }
69022
69023         function cacheIntersections(ids) {
69024             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
69025
69026             ids.forEach(function(id) {
69027                 // consider only intersections with 1 moved and 1 unmoved way.
69028                 var childNodes = graph.childNodes(graph.entity(id));
69029                 childNodes.forEach(function(node) {
69030                     var parents = graph.parentWays(node);
69031                     if (parents.length !== 2) return;
69032
69033                     var moved = graph.entity(id),
69034                         unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
69035                     if (!unmoved) return;
69036
69037                     // exclude ways that are overly connected..
69038                     if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
69039
69040                     if (moved.isArea() || unmoved.isArea()) return;
69041
69042                     cache.intersection[node.id] = {
69043                         nodeId: node.id,
69044                         movedId: moved.id,
69045                         unmovedId: unmoved.id,
69046                         movedIsEP: isEndpoint(moved, node.id),
69047                         unmovedIsEP: isEndpoint(unmoved, node.id)
69048                     };
69049                 });
69050             });
69051         }
69052
69053
69054         if (!cache) {
69055             cache = {};
69056         }
69057         if (!cache.ok) {
69058             cache.moving = {};
69059             cache.intersection = {};
69060             cache.replacedVertex = {};
69061             cache.startLoc = {};
69062             cache.nodes = [];
69063             cache.ways = [];
69064
69065             cacheEntities(moveIds);
69066             cacheIntersections(cache.ways);
69067             cache.nodes = lodash.filter(cache.nodes, canMove);
69068
69069             cache.ok = true;
69070         }
69071     }
69072
69073
69074     // Place a vertex where the moved vertex used to be, to preserve way shape..
69075     function replaceMovedVertex(nodeId, wayId, graph, delta) {
69076         var way = graph.entity(wayId),
69077             moved = graph.entity(nodeId),
69078             movedIndex = way.nodes.indexOf(nodeId),
69079             len, prevIndex, nextIndex;
69080
69081         if (way.isClosed()) {
69082             len = way.nodes.length - 1;
69083             prevIndex = (movedIndex + len - 1) % len;
69084             nextIndex = (movedIndex + len + 1) % len;
69085         } else {
69086             len = way.nodes.length;
69087             prevIndex = movedIndex - 1;
69088             nextIndex = movedIndex + 1;
69089         }
69090
69091         var prev = graph.hasEntity(way.nodes[prevIndex]),
69092             next = graph.hasEntity(way.nodes[nextIndex]);
69093
69094         // Don't add orig vertex at endpoint..
69095         if (!prev || !next) return graph;
69096
69097         var key = wayId + '_' + nodeId,
69098             orig = cache.replacedVertex[key];
69099         if (!orig) {
69100             orig = osmNode();
69101             cache.replacedVertex[key] = orig;
69102             cache.startLoc[orig.id] = cache.startLoc[nodeId];
69103         }
69104
69105         var start, end;
69106         if (delta) {
69107             start = projection(cache.startLoc[nodeId]);
69108             end = projection.invert(vecAdd(start, delta));
69109         } else {
69110             end = cache.startLoc[nodeId];
69111         }
69112         orig = orig.move(end);
69113
69114         var angle = Math.abs(geoAngle(orig, prev, projection) -
69115                 geoAngle(orig, next, projection)) * 180 / Math.PI;
69116
69117         // Don't add orig vertex if it would just make a straight line..
69118         if (angle > 175 && angle < 185) return graph;
69119
69120         // Don't add orig vertex if another point is already nearby (within 10m)
69121         if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
69122             geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
69123
69124         // moving forward or backward along way?
69125         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
69126             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
69127             d1 = geoPathLength(p1),
69128             d2 = geoPathLength(p2),
69129             insertAt = (d1 < d2) ? movedIndex : nextIndex;
69130
69131         // moving around closed loop?
69132         if (way.isClosed() && insertAt === 0) insertAt = len;
69133
69134         way = way.addNode(orig.id, insertAt);
69135         return graph.replace(orig).replace(way);
69136     }
69137
69138
69139     // Reorder nodes around intersections that have moved..
69140     function unZorroIntersection(intersection, graph) {
69141         var vertex = graph.entity(intersection.nodeId),
69142             way1 = graph.entity(intersection.movedId),
69143             way2 = graph.entity(intersection.unmovedId),
69144             isEP1 = intersection.movedIsEP,
69145             isEP2 = intersection.unmovedIsEP;
69146
69147         // don't move the vertex if it is the endpoint of both ways.
69148         if (isEP1 && isEP2) return graph;
69149
69150         var nodes1 = lodash.without(graph.childNodes(way1), vertex),
69151             nodes2 = lodash.without(graph.childNodes(way2), vertex);
69152
69153         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
69154         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
69155
69156         var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
69157             edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
69158             loc;
69159
69160         // snap vertex to nearest edge (or some point between them)..
69161         if (!isEP1 && !isEP2) {
69162             var epsilon = 1e-4, maxIter = 10;
69163             for (var i = 0; i < maxIter; i++) {
69164                 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
69165                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
69166                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
69167                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
69168             }
69169         } else if (!isEP1) {
69170             loc = edge1.loc;
69171         } else {
69172             loc = edge2.loc;
69173         }
69174
69175         graph = graph.replace(vertex.move(loc));
69176
69177         // if zorro happened, reorder nodes..
69178         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
69179             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
69180             graph = graph.replace(way1);
69181         }
69182         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
69183             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
69184             graph = graph.replace(way2);
69185         }
69186
69187         return graph;
69188     }
69189
69190
69191     function cleanupIntersections(graph) {
69192         lodash.each(cache.intersection, function(obj) {
69193             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
69194             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
69195             graph = unZorroIntersection(obj, graph);
69196         });
69197
69198         return graph;
69199     }
69200
69201
69202     // check if moving way endpoint can cross an unmoved way, if so limit delta..
69203     function limitDelta(graph) {
69204         lodash.each(cache.intersection, function(obj) {
69205             // Don't limit movement if this is vertex joins 2 endpoints..
69206             if (obj.movedIsEP && obj.unmovedIsEP) return;
69207             // Don't limit movement if this vertex is not an endpoint anyway..
69208             if (!obj.movedIsEP) return;
69209
69210             var node = graph.entity(obj.nodeId),
69211                 start = projection(node.loc),
69212                 end = vecAdd(start, delta),
69213                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
69214                 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
69215                     function(loc) { return vecAdd(projection(loc), delta); }),
69216                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
69217                 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
69218                 hits = geoPathIntersections(movedPath, unmovedPath);
69219
69220             for (var i = 0; i < hits.length; i++) {
69221                 if (lodash.isEqual(hits[i], end)) continue;
69222                 var edge = geoChooseEdge(unmovedNodes, end, projection);
69223                 delta = vecSub(projection(edge.loc), start);
69224             }
69225         });
69226     }
69227
69228
69229     var action = function(graph) {
69230         if (delta[0] === 0 && delta[1] === 0) return graph;
69231
69232         setupCache(graph);
69233
69234         if (!lodash.isEmpty(cache.intersection)) {
69235             limitDelta(graph);
69236         }
69237
69238         lodash.each(cache.nodes, function(id) {
69239             var node = graph.entity(id),
69240                 start = projection(node.loc),
69241                 end = vecAdd(start, delta);
69242             graph = graph.replace(node.move(projection.invert(end)));
69243         });
69244
69245         if (!lodash.isEmpty(cache.intersection)) {
69246             graph = cleanupIntersections(graph);
69247         }
69248
69249         return graph;
69250     };
69251
69252
69253     action.disabled = function(graph) {
69254         function incompleteRelation(id) {
69255             var entity = graph.entity(id);
69256             return entity.type === 'relation' && !entity.isComplete(graph);
69257         }
69258
69259         if (lodash.some(moveIds, incompleteRelation))
69260             return 'incomplete_relation';
69261     };
69262
69263
69264     action.delta = function() {
69265         return delta;
69266     };
69267
69268
69269     return action;
69270 }
69271
69272 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
69273 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
69274 function actionMoveNode(nodeId, loc) {
69275     return function(graph) {
69276         return graph.replace(graph.entity(nodeId).move(loc));
69277     };
69278 }
69279
69280 function actionNoop() {
69281     return function(graph) {
69282         return graph;
69283     };
69284 }
69285
69286 /*
69287  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
69288  */
69289 function actionOrthogonalize(wayId, projection) {
69290     var threshold = 12, // degrees within right or straight to alter
69291         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
69292         upperThreshold = Math.cos(threshold * Math.PI / 180);
69293
69294
69295     var action = function(graph) {
69296         var way = graph.entity(wayId),
69297             nodes = graph.childNodes(way),
69298             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
69299             corner = {i: 0, dotp: 1},
69300             epsilon = 1e-4,
69301             i, j, score, motions;
69302
69303         if (nodes.length === 4) {
69304             for (i = 0; i < 1000; i++) {
69305                 motions = points.map(calcMotion);
69306                 points[corner.i] = addPoints(points[corner.i],motions[corner.i]);
69307                 score = corner.dotp;
69308                 if (score < epsilon) {
69309                     break;
69310                 }
69311             }
69312
69313             graph = graph.replace(graph.entity(nodes[corner.i].id)
69314                 .move(projection.invert(points[corner.i])));
69315
69316         } else {
69317             var best,
69318                 originalPoints = lodash.clone(points);
69319             score = Infinity;
69320
69321             for (i = 0; i < 1000; i++) {
69322                 motions = points.map(calcMotion);
69323                 for (j = 0; j < motions.length; j++) {
69324                     points[j] = addPoints(points[j],motions[j]);
69325                 }
69326                 var newScore = squareness(points);
69327                 if (newScore < score) {
69328                     best = lodash.clone(points);
69329                     score = newScore;
69330                 }
69331                 if (score < epsilon) {
69332                     break;
69333                 }
69334             }
69335
69336             points = best;
69337
69338             for (i = 0; i < points.length; i++) {
69339                 // only move the points that actually moved
69340                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
69341                     graph = graph.replace(graph.entity(nodes[i].id)
69342                         .move(projection.invert(points[i])));
69343                 }
69344             }
69345
69346             // remove empty nodes on straight sections
69347             for (i = 0; i < points.length; i++) {
69348                 var node = nodes[i];
69349
69350                 if (graph.parentWays(node).length > 1 ||
69351                     graph.parentRelations(node).length ||
69352                     node.hasInterestingTags()) {
69353
69354                     continue;
69355                 }
69356
69357                 var dotp = normalizedDotProduct(i, points);
69358                 if (dotp < -1 + epsilon) {
69359                     graph = actionDeleteNode(nodes[i].id)(graph);
69360                 }
69361             }
69362         }
69363
69364         return graph;
69365
69366
69367         function calcMotion(b, i, array) {
69368             var a = array[(i - 1 + array.length) % array.length],
69369                 c = array[(i + 1) % array.length],
69370                 p = subtractPoints(a, b),
69371                 q = subtractPoints(c, b),
69372                 scale, dotp;
69373
69374             scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
69375             p = normalizePoint(p, 1.0);
69376             q = normalizePoint(q, 1.0);
69377
69378             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
69379
69380             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
69381             if (array.length > 3) {
69382                 if (dotp < -0.707106781186547) {
69383                     dotp += 1.0;
69384                 }
69385             } else if (dotp && Math.abs(dotp) < corner.dotp) {
69386                 corner.i = i;
69387                 corner.dotp = Math.abs(dotp);
69388             }
69389
69390             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
69391         }
69392     };
69393
69394
69395     function squareness(points) {
69396         return points.reduce(function(sum, val, i, array) {
69397             var dotp = normalizedDotProduct(i, array);
69398
69399             dotp = filterDotProduct(dotp);
69400             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
69401         }, 0);
69402     }
69403
69404
69405     function normalizedDotProduct(i, points) {
69406         var a = points[(i - 1 + points.length) % points.length],
69407             b = points[i],
69408             c = points[(i + 1) % points.length],
69409             p = subtractPoints(a, b),
69410             q = subtractPoints(c, b);
69411
69412         p = normalizePoint(p, 1.0);
69413         q = normalizePoint(q, 1.0);
69414
69415         return p[0] * q[0] + p[1] * q[1];
69416     }
69417
69418
69419     function subtractPoints(a, b) {
69420         return [a[0] - b[0], a[1] - b[1]];
69421     }
69422
69423
69424     function addPoints(a, b) {
69425         return [a[0] + b[0], a[1] + b[1]];
69426     }
69427
69428
69429     function normalizePoint(point, scale) {
69430         var vector = [0, 0];
69431         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
69432         if (length !== 0) {
69433             vector[0] = point[0] / length;
69434             vector[1] = point[1] / length;
69435         }
69436
69437         vector[0] *= scale;
69438         vector[1] *= scale;
69439
69440         return vector;
69441     }
69442
69443
69444     function filterDotProduct(dotp) {
69445         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
69446             return dotp;
69447         }
69448
69449         return 0;
69450     }
69451
69452
69453     action.disabled = function(graph) {
69454         var way = graph.entity(wayId),
69455             nodes = graph.childNodes(way),
69456             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
69457
69458         if (squareness(points)) {
69459             return false;
69460         }
69461
69462         return 'not_squarish';
69463     };
69464
69465
69466     return action;
69467 }
69468
69469 // Split a way at the given node.
69470 //
69471 // Optionally, split only the given ways, if multiple ways share
69472 // the given node.
69473 //
69474 // This is the inverse of `iD.actionJoin`.
69475 //
69476 // For testing convenience, accepts an ID to assign to the new way.
69477 // Normally, this will be undefined and the way will automatically
69478 // be assigned a new ID.
69479 //
69480 // Reference:
69481 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
69482 //
69483 function actionSplit(nodeId, newWayIds) {
69484     var wayIds;
69485
69486     // if the way is closed, we need to search for a partner node
69487     // to split the way at.
69488     //
69489     // The following looks for a node that is both far away from
69490     // the initial node in terms of way segment length and nearby
69491     // in terms of beeline-distance. This assures that areas get
69492     // split on the most "natural" points (independent of the number
69493     // of nodes).
69494     // For example: bone-shaped areas get split across their waist
69495     // line, circles across the diameter.
69496     function splitArea(nodes, idxA, graph) {
69497         var lengths = new Array(nodes.length),
69498             length,
69499             i,
69500             best = 0,
69501             idxB;
69502
69503         function wrap(index) {
69504             return utilWrap(index, nodes.length);
69505         }
69506
69507         function dist(nA, nB) {
69508             return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
69509         }
69510
69511         // calculate lengths
69512         length = 0;
69513         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
69514             length += dist(nodes[i], nodes[wrap(i-1)]);
69515             lengths[i] = length;
69516         }
69517
69518         length = 0;
69519         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
69520             length += dist(nodes[i], nodes[wrap(i+1)]);
69521             if (length < lengths[i])
69522                 lengths[i] = length;
69523         }
69524
69525         // determine best opposite node to split
69526         for (i = 0; i < nodes.length; i++) {
69527             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
69528             if (cost > best) {
69529                 idxB = i;
69530                 best = cost;
69531             }
69532         }
69533
69534         return idxB;
69535     }
69536
69537
69538     function split(graph, wayA, newWayId) {
69539         var wayB = osmWay({id: newWayId, tags: wayA.tags}),
69540             nodesA,
69541             nodesB,
69542             isArea = wayA.isArea(),
69543             isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
69544
69545         if (wayA.isClosed()) {
69546             var nodes = wayA.nodes.slice(0, -1),
69547                 idxA = lodash.indexOf(nodes, nodeId),
69548                 idxB = splitArea(nodes, idxA, graph);
69549
69550             if (idxB < idxA) {
69551                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
69552                 nodesB = nodes.slice(idxB, idxA + 1);
69553             } else {
69554                 nodesA = nodes.slice(idxA, idxB + 1);
69555                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
69556             }
69557         } else {
69558             var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
69559             nodesA = wayA.nodes.slice(0, idx + 1);
69560             nodesB = wayA.nodes.slice(idx);
69561         }
69562
69563         wayA = wayA.update({nodes: nodesA});
69564         wayB = wayB.update({nodes: nodesB});
69565
69566         graph = graph.replace(wayA);
69567         graph = graph.replace(wayB);
69568
69569         graph.parentRelations(wayA).forEach(function(relation) {
69570             if (relation.isRestriction()) {
69571                 var via = relation.memberByRole('via');
69572                 if (via && wayB.contains(via.id)) {
69573                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
69574                     graph = graph.replace(relation);
69575                 }
69576             } else {
69577                 if (relation === isOuter) {
69578                     graph = graph.replace(relation.mergeTags(wayA.tags));
69579                     graph = graph.replace(wayA.update({tags: {}}));
69580                     graph = graph.replace(wayB.update({tags: {}}));
69581                 }
69582
69583                 var member = {
69584                     id: wayB.id,
69585                     type: 'way',
69586                     role: relation.memberById(wayA.id).role
69587                 };
69588
69589                 graph = actionAddMember(relation.id, member)(graph);
69590             }
69591         });
69592
69593         if (!isOuter && isArea) {
69594             var multipolygon = osmRelation({
69595                 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
69596                 members: [
69597                     {id: wayA.id, role: 'outer', type: 'way'},
69598                     {id: wayB.id, role: 'outer', type: 'way'}
69599                 ]});
69600
69601             graph = graph.replace(multipolygon);
69602             graph = graph.replace(wayA.update({tags: {}}));
69603             graph = graph.replace(wayB.update({tags: {}}));
69604         }
69605
69606         return graph;
69607     }
69608
69609
69610     var action = function(graph) {
69611         var candidates = action.ways(graph);
69612         for (var i = 0; i < candidates.length; i++) {
69613             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
69614         }
69615         return graph;
69616     };
69617
69618
69619     action.ways = function(graph) {
69620         var node = graph.entity(nodeId),
69621             parents = graph.parentWays(node),
69622             hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
69623
69624         return parents.filter(function(parent) {
69625             if (wayIds && wayIds.indexOf(parent.id) === -1)
69626                 return false;
69627
69628             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
69629                 return false;
69630
69631             if (parent.isClosed()) {
69632                 return true;
69633             }
69634
69635             for (var i = 1; i < parent.nodes.length - 1; i++) {
69636                 if (parent.nodes[i] === nodeId) {
69637                     return true;
69638                 }
69639             }
69640
69641             return false;
69642         });
69643     };
69644
69645
69646     action.disabled = function(graph) {
69647         var candidates = action.ways(graph);
69648         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
69649             return 'not_eligible';
69650     };
69651
69652
69653     action.limitWays = function(_) {
69654         if (!arguments.length) return wayIds;
69655         wayIds = _;
69656         return action;
69657     };
69658
69659
69660     return action;
69661 }
69662
69663 // Create a restriction relation for `turn`, which must have the following structure:
69664 //
69665 //     {
69666 //         from: { node: <node ID>, way: <way ID> },
69667 //         via:  { node: <node ID> },
69668 //         to:   { node: <node ID>, way: <way ID> },
69669 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
69670 //     }
69671 //
69672 // This specifies a restriction of type `restriction` when traveling from
69673 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
69674 // (The action does not check that these entities form a valid intersection.)
69675 //
69676 // If `restriction` is not provided, it is automatically determined by
69677 // osmInferRestriction.
69678 //
69679 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
69680 // and `to.node` are used to determine which portion of the split ways become
69681 // members of the restriction.
69682 //
69683 // For testing convenience, accepts an ID to assign to the new relation.
69684 // Normally, this will be undefined and the relation will automatically
69685 // be assigned a new ID.
69686 //
69687 function actionRestrictTurn(turn, projection, restrictionId) {
69688
69689     return function(graph) {
69690         var from = graph.entity(turn.from.way),
69691             via  = graph.entity(turn.via.node),
69692             to   = graph.entity(turn.to.way);
69693
69694         function isClosingNode(way, nodeId) {
69695             return nodeId === way.first() && nodeId === way.last();
69696         }
69697
69698         function split(toOrFrom) {
69699             var newID = toOrFrom.newID || osmWay().id;
69700             graph = actionSplit(via.id, [newID])
69701                 .limitWays([toOrFrom.way])(graph);
69702
69703             var a = graph.entity(newID),
69704                 b = graph.entity(toOrFrom.way);
69705
69706             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
69707                 return [a, b];
69708             } else {
69709                 return [b, a];
69710             }
69711         }
69712
69713         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
69714             if (turn.from.node === turn.to.node) {
69715                 // U-turn
69716                 from = to = split(turn.from)[0];
69717             } else if (turn.from.way === turn.to.way) {
69718                 // Straight-on or circular
69719                 var s = split(turn.from);
69720                 from = s[0];
69721                 to   = s[1];
69722             } else {
69723                 // Other
69724                 from = split(turn.from)[0];
69725             }
69726         }
69727
69728         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
69729             to = split(turn.to)[0];
69730         }
69731
69732         return graph.replace(osmRelation({
69733             id: restrictionId,
69734             tags: {
69735                 type: 'restriction',
69736                 restriction: turn.restriction ||
69737                     osmInferRestriction(
69738                         graph,
69739                         turn.from,
69740                         turn.via,
69741                         turn.to,
69742                         projection)
69743             },
69744             members: [
69745                 {id: from.id, type: 'way',  role: 'from'},
69746                 {id: via.id,  type: 'node', role: 'via'},
69747                 {id: to.id,   type: 'way',  role: 'to'}
69748             ]
69749         }));
69750     };
69751 }
69752
69753 function actionRevert(id) {
69754     var action = function(graph) {
69755         var entity = graph.hasEntity(id),
69756             base = graph.base().entities[id];
69757
69758         if (entity && !base) {    // entity will be removed..
69759             if (entity.type === 'node') {
69760                 graph.parentWays(entity)
69761                     .forEach(function(parent) {
69762                         parent = parent.removeNode(id);
69763                         graph = graph.replace(parent);
69764
69765                         if (parent.isDegenerate()) {
69766                             graph = actionDeleteWay(parent.id)(graph);
69767                         }
69768                     });
69769             }
69770
69771             graph.parentRelations(entity)
69772                 .forEach(function(parent) {
69773                     parent = parent.removeMembersWithID(id);
69774                     graph = graph.replace(parent);
69775
69776                     if (parent.isDegenerate()) {
69777                         graph = actionDeleteRelation(parent.id)(graph);
69778                     }
69779                 });
69780         }
69781
69782         return graph.revert(id);
69783     };
69784
69785     return action;
69786 }
69787
69788 function actionRotateWay(wayId, pivot, angle, projection) {
69789     return function(graph) {
69790         return graph.update(function(graph) {
69791             var way = graph.entity(wayId);
69792
69793             lodash.uniq(way.nodes).forEach(function(id) {
69794
69795                 var node = graph.entity(id),
69796                     point = projection(node.loc),
69797                     radial = [0,0];
69798
69799                 radial[0] = point[0] - pivot[0];
69800                 radial[1] = point[1] - pivot[1];
69801
69802                 point = [
69803                     radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + pivot[0],
69804                     radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + pivot[1]
69805                 ];
69806
69807                 graph = graph.replace(node.move(projection.invert(point)));
69808
69809             });
69810
69811         });
69812     };
69813 }
69814
69815 /*
69816  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
69817  */
69818 function actionStraighten(wayId, projection) {
69819
69820     function positionAlongWay(n, s, e) {
69821         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1]))/
69822                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
69823     }
69824
69825
69826     var action = function(graph) {
69827         var way = graph.entity(wayId),
69828             nodes = graph.childNodes(way),
69829             points = nodes.map(function(n) { return projection(n.loc); }),
69830             startPoint = points[0],
69831             endPoint = points[points.length-1],
69832             toDelete = [],
69833             i;
69834
69835         for (i = 1; i < points.length-1; i++) {
69836             var node = nodes[i],
69837                 point = points[i];
69838
69839             if (graph.parentWays(node).length > 1 ||
69840                 graph.parentRelations(node).length ||
69841                 node.hasInterestingTags()) {
69842
69843                 var u = positionAlongWay(point, startPoint, endPoint),
69844                     p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
69845                     p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]);
69846
69847                 graph = graph
69848                     .replace(graph.entity(node.id)
69849                     .move(projection.invert([p0, p1])));
69850
69851             } else {
69852                 // safe to delete
69853                 if (toDelete.indexOf(node) === -1) {
69854                     toDelete.push(node);
69855                 }
69856             }
69857         }
69858
69859         for (i = 0; i < toDelete.length; i++) {
69860             graph = actionDeleteNode(toDelete[i].id)(graph);
69861         }
69862
69863         return graph;
69864     };
69865
69866
69867     action.disabled = function(graph) {
69868         // check way isn't too bendy
69869         var way = graph.entity(wayId),
69870             nodes = graph.childNodes(way),
69871             points = nodes.map(function(n) { return projection(n.loc); }),
69872             startPoint = points[0],
69873             endPoint = points[points.length-1],
69874             threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
69875             i;
69876
69877         if (threshold === 0) {
69878             return 'too_bendy';
69879         }
69880
69881         for (i = 1; i < points.length-1; i++) {
69882             var point = points[i],
69883                 u = positionAlongWay(point, startPoint, endPoint),
69884                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
69885                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
69886                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
69887
69888             // to bendy if point is off by 20% of total start/end distance in projected space
69889             if (isNaN(dist) || dist > threshold) {
69890                 return 'too_bendy';
69891             }
69892         }
69893     };
69894
69895
69896     return action;
69897 }
69898
69899 // Remove the effects of `turn.restriction` on `turn`, which must have the
69900 // following structure:
69901 //
69902 //     {
69903 //         from: { node: <node ID>, way: <way ID> },
69904 //         via:  { node: <node ID> },
69905 //         to:   { node: <node ID>, way: <way ID> },
69906 //         restriction: <relation ID>
69907 //     }
69908 //
69909 // In the simple case, `restriction` is a reference to a `no_*` restriction
69910 // on the turn itself. In this case, it is simply deleted.
69911 //
69912 // The more complex case is where `restriction` references an `only_*`
69913 // restriction on a different turn in the same intersection. In that case,
69914 // that restriction is also deleted, but at the same time restrictions on
69915 // the turns other than the first two are created.
69916 //
69917 function actionUnrestrictTurn(turn) {
69918     return function(graph) {
69919         return actionDeleteRelation(turn.restriction)(graph);
69920     };
69921 }
69922
69923
69924
69925 var index$16 = Object.freeze({
69926         d3combobox: d3combobox,
69927         d3geoTile: d3geoTile,
69928         d3keybinding: d3keybinding
69929 });
69930
69931 /* export some legacy symbols: */
69932 var Connection = services.osm;
69933 var debug = false;
69934
69935
69936
69937
69938 var iD = Object.freeze({
69939         Connection: Connection,
69940         debug: debug,
69941         d3: index$1,
69942         lib: index$16,
69943         Context: coreContext,
69944         setAreaKeys: setAreaKeys,
69945         Difference: coreDifference,
69946         Graph: coreGraph$$1,
69947         History: coreHistory,
69948         Tree: coreTree,
69949         Entity: osmEntity$$1,
69950         Node: osmNode,
69951         Relation: osmRelation,
69952         Way: osmWay,
69953         BackgroundSource: rendererBackgroundSource,
69954         Background: rendererBackground,
69955         Features: rendererFeatures,
69956         Map: rendererMap,
69957         TileLayer: rendererTileLayer,
69958         Detect: utilDetect,
69959         actionAddEntity: actionAddEntity,
69960         actionAddMember: actionAddMember,
69961         actionAddMidpoint: actionAddMidpoint,
69962         actionAddVertex: actionAddVertex,
69963         actionChangeMember: actionChangeMember,
69964         actionChangePreset: actionChangePreset,
69965         actionChangeTags: actionChangeTags,
69966         actionCircularize: actionCircularize,
69967         actionConnect: actionConnect,
69968         actionCopyEntities: actionCopyEntities,
69969         actionDeleteMember: actionDeleteMember,
69970         actionDeleteMultiple: actionDeleteMultiple,
69971         actionDeleteNode: actionDeleteNode,
69972         actionDeleteRelation: actionDeleteRelation,
69973         actionDeleteWay: actionDeleteWay,
69974         actionDeprecateTags: actionDeprecateTags,
69975         actionDiscardTags: actionDiscardTags,
69976         actionDisconnect: actionDisconnect,
69977         actionJoin: actionJoin,
69978         actionMerge: actionMerge,
69979         actionMergePolygon: actionMergePolygon,
69980         actionMergeRemoteChanges: actionMergeRemoteChanges,
69981         actionMove: actionMove,
69982         actionMoveNode: actionMoveNode,
69983         actionNoop: actionNoop,
69984         actionOrthogonalize: actionOrthogonalize,
69985         actionRestrictTurn: actionRestrictTurn,
69986         actionReverse: actionReverse,
69987         actionRevert: actionRevert,
69988         actionRotateWay: actionRotateWay,
69989         actionSplit: actionSplit,
69990         actionStraighten: actionStraighten,
69991         actionUnrestrictTurn: actionUnrestrictTurn,
69992         behaviorAddWay: behaviorAddWay,
69993         behaviorBreathe: behaviorBreathe,
69994         behaviorCopy: behaviorCopy,
69995         behaviorDrag: behaviorDrag,
69996         behaviorDrawWay: behaviorDrawWay,
69997         behaviorDraw: behaviorDraw,
69998         behaviorEdit: behaviorEdit,
69999         behaviorHash: behaviorHash,
70000         behaviorHover: behaviorHover,
70001         behaviorLasso: behaviorLasso,
70002         behaviorPaste: behaviorPaste,
70003         behaviorSelect: behaviorSelect,
70004         behaviorTail: behaviorTail,
70005         coreContext: coreContext,
70006         coreDifference: coreDifference,
70007         coreGraph: coreGraph$$1,
70008         coreHistory: coreHistory,
70009         coreTree: coreTree,
70010         data: data,
70011         dataWikipedia: dataWikipedia,
70012         dataFeatureIcons: dataFeatureIcons,
70013         dataSuggestions: dataSuggestions,
70014         dataAddressFormats: dataAddressFormats,
70015         dataDeprecated: dataDeprecated,
70016         dataDiscarded: dataDiscarded,
70017         dataLocales: dataLocales,
70018         dataPhoneFormats: dataPhoneFormats,
70019         dataImperial: dataImperial,
70020         dataDriveLeft: dataDriveLeft,
70021         dataEn: en,
70022         geoRoundCoords: geoRoundCoords,
70023         geoInterp: geoInterp,
70024         geoCross: geoCross,
70025         geoEuclideanDistance: geoEuclideanDistance,
70026         geoLatToMeters: geoLatToMeters,
70027         geoLonToMeters: geoLonToMeters,
70028         geoMetersToLat: geoMetersToLat,
70029         geoMetersToLon: geoMetersToLon,
70030         geoOffsetToMeters: geoOffsetToMeters,
70031         geoMetersToOffset: geoMetersToOffset,
70032         geoSphericalDistance: geoSphericalDistance,
70033         geoEdgeEqual: geoEdgeEqual,
70034         geoAngle: geoAngle,
70035         geoChooseEdge: geoChooseEdge,
70036         geoLineIntersection: geoLineIntersection,
70037         geoPathIntersections: geoPathIntersections,
70038         geoPointInPolygon: geoPointInPolygon,
70039         geoPolygonContainsPolygon: geoPolygonContainsPolygon,
70040         geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
70041         geoPathLength: geoPathLength,
70042         geoExtent: geoExtent$$1,
70043         geoRawMercator: geoRawMercator,
70044         modeAddArea: modeAddArea$$1,
70045         modeAddLine: modeAddLine$$1,
70046         modeAddPoint: modeAddPoint$$1,
70047         modeBrowse: modeBrowse$$1,
70048         modeDragNode: modeDragNode$$1,
70049         modeDrawArea: modeDrawArea,
70050         modeDrawLine: modeDrawLine,
70051         modeMove: modeMove$$1,
70052         modeRotateWay: modeRotateWay$$1,
70053         modeSave: modeSave$$1,
70054         modeSelect: modeSelect,
70055         operationCircularize: operationCircularize,
70056         operationContinue: operationContinue,
70057         operationDelete: operationDelete,
70058         operationDisconnect: operationDisconnect,
70059         operationMerge: operationMerge,
70060         operationMove: operationMove,
70061         operationOrthogonalize: operationOrthogonalize,
70062         operationReverse: operationReverse,
70063         operationRotate: operationRotate,
70064         operationSplit: operationSplit,
70065         operationStraighten: operationStraighten,
70066         osmEntity: osmEntity$$1,
70067         osmNode: osmNode,
70068         osmRelation: osmRelation,
70069         osmWay: osmWay,
70070         osmIntersection: osmIntersection,
70071         osmTurn: osmTurn,
70072         osmInferRestriction: osmInferRestriction,
70073         osmLanes: osmLanes,
70074         osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
70075         osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
70076         osmJoinWays: osmJoinWays,
70077         osmOneWayTags: osmOneWayTags,
70078         osmPavedTags: osmPavedTags,
70079         osmIsInterestingTag: osmIsInterestingTag,
70080         presetCategory: presetCategory,
70081         presetCollection: presetCollection,
70082         presetField: presetField,
70083         presetPreset: presetPreset,
70084         presetIndex: presetIndex,
70085         rendererBackgroundSource: rendererBackgroundSource,
70086         rendererBackground: rendererBackground,
70087         rendererFeatures: rendererFeatures,
70088         rendererMap: rendererMap,
70089         rendererTileLayer: rendererTileLayer,
70090         services: services,
70091         svgAreas: svgAreas$$1,
70092         svgDebug: svgDebug,
70093         svgDefs: svgDefs,
70094         svgGpx: svgGpx,
70095         svgIcon: svgIcon,
70096         svgLabels: svgLabels,
70097         svgLayers: svgLayers,
70098         svgLines: svgLines$$1,
70099         svgMapillaryImages: svgMapillaryImages,
70100         svgMapillarySigns: svgMapillarySigns,
70101         svgMidpoints: svgMidpoints$$1,
70102         svgOneWaySegments: svgOneWaySegments,
70103         svgOsm: svgOsm,
70104         svgPath: svgPath,
70105         svgPointTransform: svgPointTransform,
70106         svgPoints: svgPoints$$1,
70107         svgRelationMemberTags: svgRelationMemberTags,
70108         svgTagClasses: svgTagClasses,
70109         svgTurns: svgTurns,
70110         svgVertices: svgVertices$$1,
70111         uiFields: uiFields,
70112         uiFieldDefaultcheck: uiFieldCheck,
70113         uiFieldCheck: uiFieldCheck,
70114         uiFieldTypeCombo: uiFieldCombo,
70115         uiFieldMultiCombo: uiFieldCombo,
70116         uiFieldNetworkCombo: uiFieldCombo,
70117         uiFieldCombo: uiFieldCombo,
70118         uiFieldUrl: uiFieldText,
70119         uiFieldNumber: uiFieldText,
70120         uiFieldTel: uiFieldText,
70121         uiFieldEmail: uiFieldText,
70122         uiFieldText: uiFieldText,
70123         uiFieldAccess: uiFieldAccess,
70124         uiFieldAddress: uiFieldAddress,
70125         uiFieldCycleway: uiFieldCycleway,
70126         uiFieldLanes: uiFieldLanes,
70127         uiFieldLocalized: uiFieldLocalized,
70128         uiFieldMaxspeed: uiFieldMaxspeed,
70129         uiFieldRadio: uiFieldRadio,
70130         uiFieldRestrictions: uiFieldRestrictions,
70131         uiFieldTextarea: uiFieldTextarea,
70132         uiFieldWikipedia: uiFieldWikipedia,
70133         uiIntro: uiIntro,
70134         uiInit: uiInit,
70135         uiAccount: uiAccount,
70136         uiAttribution: uiAttribution,
70137         uiBackground: uiBackground,
70138         uiCmd: uiCmd,
70139         uiCommit: uiCommit,
70140         uiConfirm: uiConfirm,
70141         uiConflicts: uiConflicts,
70142         uiContributors: uiContributors,
70143         uiDisclosure: uiDisclosure,
70144         uiEntityEditor: uiEntityEditor,
70145         uiFeatureInfo: uiFeatureInfo,
70146         uiFeatureList: uiFeatureList,
70147         uiFlash: uiFlash,
70148         uiFullScreen: uiFullScreen,
70149         uiGeolocate: uiGeolocate,
70150         uiHelp: uiHelp,
70151         uiInfo: uiInfo,
70152         uiInspector: uiInspector,
70153         uiLasso: uiLasso,
70154         uiLoading: uiLoading,
70155         uiMapData: uiMapData,
70156         uiMapInMap: uiMapInMap,
70157         uiModal: uiModal,
70158         uiModes: uiModes,
70159         uiNotice: uiNotice,
70160         uiPreset: uiPreset,
70161         uiPresetIcon: uiPresetIcon,
70162         uiPresetList: uiPresetList,
70163         uiRadialMenu: uiRadialMenu,
70164         uiRawMemberEditor: uiRawMemberEditor,
70165         uiRawMembershipEditor: uiRawMembershipEditor,
70166         uiRawTagEditor: uiRawTagEditor,
70167         uiRestore: uiRestore,
70168         uiSave: uiSave,
70169         uiScale: uiScale,
70170         uiSelectionList: uiSelectionList,
70171         uiSidebar: uiSidebar,
70172         uiSourceSwitch: uiSourceSwitch,
70173         uiSpinner: uiSpinner,
70174         uiSplash: uiSplash,
70175         uiStatus: uiStatus,
70176         uiSuccess: uiSuccess,
70177         uiTagReference: uiTagReference,
70178         uiToggle: uiToggle,
70179         uiTooltipHtml: uiTooltipHtml,
70180         uiUndoRedo: uiUndoRedo,
70181         uiViewOnOSM: uiViewOnOSM,
70182         uiZoom: uiZoom,
70183         utilTagText: utilTagText,
70184         utilEntitySelector: utilEntitySelector,
70185         utilEntityOrMemberSelector: utilEntityOrMemberSelector,
70186         utilDisplayName: utilDisplayName,
70187         utilDisplayType: utilDisplayType,
70188         utilStringQs: utilStringQs,
70189         utilQsString: utilQsString,
70190         utilPrefixDOMProperty: utilPrefixDOMProperty,
70191         utilPrefixCSSProperty: utilPrefixCSSProperty,
70192         utilSetTransform: utilSetTransform,
70193         utilEditDistance: utilEditDistance,
70194         utilFastMouse: utilFastMouse,
70195         utilGetPrototypeOf: utilGetPrototypeOf,
70196         utilAsyncMap: utilAsyncMap,
70197         utilWrap: utilWrap,
70198         utilFunctor: utilFunctor,
70199         utilSessionMutex: utilSessionMutex,
70200         utilSuggestNames: utilSuggestNames,
70201         utilTriggerEvent: utilTriggerEvent,
70202         utilGetSetValue: utilGetSetValue,
70203         d3combobox: d3combobox,
70204         d3geoTile: d3geoTile,
70205         d3keybinding: d3keybinding,
70206         validationDeprecatedTag: validationDeprecatedTag,
70207         validationManyDeletions: validationManyDeletions,
70208         validationMissingTag: validationMissingTag,
70209         validationTagSuggestsArea: validationTagSuggestsArea
70210 });
70211
70212 window.iD = iD;
70213
70214 }());
70215 //# sourceMappingURL=iD.js.map